forked from suyu/suyu
GPU: Bind and clear the render target when the CLEAR_BUFFERS register is written to.
This commit is contained in:
parent
827bb08c91
commit
be51120d23
4 changed files with 86 additions and 0 deletions
|
@ -126,6 +126,10 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
|
||||||
DrawArrays();
|
DrawArrays();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MAXWELL3D_REG_INDEX(clear_buffers): {
|
||||||
|
ProcessClearBuffers();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MAXWELL3D_REG_INDEX(query.query_get): {
|
case MAXWELL3D_REG_INDEX(query.query_get): {
|
||||||
ProcessQueryGet();
|
ProcessQueryGet();
|
||||||
break;
|
break;
|
||||||
|
@ -415,5 +419,12 @@ bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Maxwell3D::ProcessClearBuffers() {
|
||||||
|
ASSERT(regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B &&
|
||||||
|
regs.clear_buffers.A);
|
||||||
|
|
||||||
|
VideoCore::g_renderer->Rasterizer()->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Engines
|
} // namespace Engines
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
|
@ -19,6 +19,9 @@ public:
|
||||||
/// Draw the current batch of vertex arrays
|
/// Draw the current batch of vertex arrays
|
||||||
virtual void DrawArrays() = 0;
|
virtual void DrawArrays() = 0;
|
||||||
|
|
||||||
|
/// Clear the current framebuffer
|
||||||
|
virtual void Clear() = 0;
|
||||||
|
|
||||||
/// Notify rasterizer that the specified Maxwell register has been changed
|
/// Notify rasterizer that the specified Maxwell register has been changed
|
||||||
virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
|
virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
|
||||||
|
|
||||||
|
|
|
@ -297,6 +297,77 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::Clear() {
|
||||||
|
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
// TODO(bunnei): Implement these
|
||||||
|
const bool has_stencil = false;
|
||||||
|
const bool using_color_fb = true;
|
||||||
|
const bool using_depth_fb = regs.zeta.Address() != 0;
|
||||||
|
const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
|
||||||
|
|
||||||
|
const bool write_color_fb =
|
||||||
|
state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
|
||||||
|
state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE;
|
||||||
|
|
||||||
|
const bool write_depth_fb =
|
||||||
|
(state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
|
||||||
|
(has_stencil && state.stencil.test_enabled && state.stencil.write_mask != 0);
|
||||||
|
|
||||||
|
Surface color_surface;
|
||||||
|
Surface depth_surface;
|
||||||
|
MathUtil::Rectangle<u32> surfaces_rect;
|
||||||
|
std::tie(color_surface, depth_surface, surfaces_rect) =
|
||||||
|
res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, viewport_rect);
|
||||||
|
|
||||||
|
MathUtil::Rectangle<u32> draw_rect{
|
||||||
|
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left,
|
||||||
|
surfaces_rect.left, surfaces_rect.right)), // Left
|
||||||
|
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top,
|
||||||
|
surfaces_rect.bottom, surfaces_rect.top)), // Top
|
||||||
|
static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right,
|
||||||
|
surfaces_rect.left, surfaces_rect.right)), // Right
|
||||||
|
static_cast<u32>(
|
||||||
|
std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.bottom,
|
||||||
|
surfaces_rect.bottom, surfaces_rect.top))}; // Bottom
|
||||||
|
|
||||||
|
// Bind the framebuffer surfaces
|
||||||
|
BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
|
||||||
|
|
||||||
|
// Sync the viewport
|
||||||
|
SyncViewport(surfaces_rect);
|
||||||
|
|
||||||
|
// TODO(bunnei): Sync scissorbox uniform(s) here
|
||||||
|
|
||||||
|
// Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
|
||||||
|
// scissor test to prevent drawing outside of the framebuffer region
|
||||||
|
state.scissor.enabled = true;
|
||||||
|
state.scissor.x = draw_rect.left;
|
||||||
|
state.scissor.y = draw_rect.bottom;
|
||||||
|
state.scissor.width = draw_rect.GetWidth();
|
||||||
|
state.scissor.height = draw_rect.GetHeight();
|
||||||
|
state.Apply();
|
||||||
|
|
||||||
|
// TODO(Subv): Support clearing only partial colors.
|
||||||
|
glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
|
||||||
|
regs.clear_color[3]);
|
||||||
|
glClearDepth(regs.clear_depth);
|
||||||
|
|
||||||
|
GLbitfield clear_mask = GL_COLOR_BUFFER_BIT;
|
||||||
|
if (regs.clear_buffers.Z)
|
||||||
|
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||||||
|
|
||||||
|
glClear(clear_mask);
|
||||||
|
|
||||||
|
// Mark framebuffer surfaces as dirty
|
||||||
|
if (color_surface != nullptr && write_color_fb) {
|
||||||
|
res_cache.MarkSurfaceAsDirty(color_surface);
|
||||||
|
}
|
||||||
|
if (depth_surface != nullptr && write_depth_fb) {
|
||||||
|
res_cache.MarkSurfaceAsDirty(depth_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::DrawArrays() {
|
void RasterizerOpenGL::DrawArrays() {
|
||||||
if (accelerate_draw == AccelDraw::Disabled)
|
if (accelerate_draw == AccelDraw::Disabled)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
~RasterizerOpenGL() override;
|
~RasterizerOpenGL() override;
|
||||||
|
|
||||||
void DrawArrays() override;
|
void DrawArrays() override;
|
||||||
|
void Clear() override;
|
||||||
void NotifyMaxwellRegisterChanged(u32 method) override;
|
void NotifyMaxwellRegisterChanged(u32 method) override;
|
||||||
void FlushAll() override;
|
void FlushAll() override;
|
||||||
void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
|
void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
|
||||||
|
|
Loading…
Reference in a new issue