mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-23 17:00:57 +01:00
Merge pull request #609 from Subv/clear_buffers
GPU: Implemented the CLEAR_BUFFERS register.
This commit is contained in:
commit
c996787d84
5 changed files with 105 additions and 16 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,13 @@ bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Maxwell3D::ProcessClearBuffers() {
|
||||||
|
ASSERT(regs.clear_buffers.R == regs.clear_buffers.G &&
|
||||||
|
regs.clear_buffers.R == regs.clear_buffers.B &&
|
||||||
|
regs.clear_buffers.R == regs.clear_buffers.A);
|
||||||
|
|
||||||
|
VideoCore::g_renderer->Rasterizer()->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Engines
|
} // namespace Engines
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
|
@ -436,7 +436,12 @@ public:
|
||||||
u32 count;
|
u32 count;
|
||||||
} vertex_buffer;
|
} vertex_buffer;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x99);
|
INSERT_PADDING_WORDS(1);
|
||||||
|
|
||||||
|
float clear_color[4];
|
||||||
|
float clear_depth;
|
||||||
|
|
||||||
|
INSERT_PADDING_WORDS(0x93);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 address_high;
|
u32 address_high;
|
||||||
|
@ -584,7 +589,21 @@ public:
|
||||||
|
|
||||||
Cull cull;
|
Cull cull;
|
||||||
|
|
||||||
INSERT_PADDING_WORDS(0x77);
|
INSERT_PADDING_WORDS(0x2B);
|
||||||
|
|
||||||
|
union {
|
||||||
|
u32 raw;
|
||||||
|
BitField<0, 1, u32> Z;
|
||||||
|
BitField<1, 1, u32> S;
|
||||||
|
BitField<2, 1, u32> R;
|
||||||
|
BitField<3, 1, u32> G;
|
||||||
|
BitField<4, 1, u32> B;
|
||||||
|
BitField<5, 1, u32> A;
|
||||||
|
BitField<6, 4, u32> RT;
|
||||||
|
BitField<10, 11, u32> layer;
|
||||||
|
} clear_buffers;
|
||||||
|
|
||||||
|
INSERT_PADDING_WORDS(0x4B);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
u32 query_address_high;
|
u32 query_address_high;
|
||||||
|
@ -766,6 +785,9 @@ private:
|
||||||
/// Handles writes to the macro uploading registers.
|
/// Handles writes to the macro uploading registers.
|
||||||
void ProcessMacroUpload(u32 data);
|
void ProcessMacroUpload(u32 data);
|
||||||
|
|
||||||
|
/// Handles a write to the CLEAR_BUFFERS register.
|
||||||
|
void ProcessClearBuffers();
|
||||||
|
|
||||||
/// Handles a write to the QUERY_GET register.
|
/// Handles a write to the QUERY_GET register.
|
||||||
void ProcessQueryGet();
|
void ProcessQueryGet();
|
||||||
|
|
||||||
|
@ -788,6 +810,8 @@ ASSERT_REG_POSITION(rt, 0x200);
|
||||||
ASSERT_REG_POSITION(viewport_transform[0], 0x280);
|
ASSERT_REG_POSITION(viewport_transform[0], 0x280);
|
||||||
ASSERT_REG_POSITION(viewport, 0x300);
|
ASSERT_REG_POSITION(viewport, 0x300);
|
||||||
ASSERT_REG_POSITION(vertex_buffer, 0x35D);
|
ASSERT_REG_POSITION(vertex_buffer, 0x35D);
|
||||||
|
ASSERT_REG_POSITION(clear_color[0], 0x360);
|
||||||
|
ASSERT_REG_POSITION(clear_depth, 0x364);
|
||||||
ASSERT_REG_POSITION(zeta, 0x3F8);
|
ASSERT_REG_POSITION(zeta, 0x3F8);
|
||||||
ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
|
ASSERT_REG_POSITION(vertex_attrib_format[0], 0x458);
|
||||||
ASSERT_REG_POSITION(rt_control, 0x487);
|
ASSERT_REG_POSITION(rt_control, 0x487);
|
||||||
|
@ -803,6 +827,7 @@ ASSERT_REG_POSITION(code_address, 0x582);
|
||||||
ASSERT_REG_POSITION(draw, 0x585);
|
ASSERT_REG_POSITION(draw, 0x585);
|
||||||
ASSERT_REG_POSITION(index_array, 0x5F2);
|
ASSERT_REG_POSITION(index_array, 0x5F2);
|
||||||
ASSERT_REG_POSITION(cull, 0x646);
|
ASSERT_REG_POSITION(cull, 0x646);
|
||||||
|
ASSERT_REG_POSITION(clear_buffers, 0x674);
|
||||||
ASSERT_REG_POSITION(query, 0x6C0);
|
ASSERT_REG_POSITION(query, 0x6C0);
|
||||||
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
||||||
ASSERT_REG_POSITION(independent_blend, 0x780);
|
ASSERT_REG_POSITION(independent_blend, 0x780);
|
||||||
|
|
|
@ -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,11 +297,7 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::DrawArrays() {
|
std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
|
||||||
if (accelerate_draw == AccelDraw::Disabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
|
||||||
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
// Sync the depth test state before configuring the framebuffer surfaces.
|
// Sync the depth test state before configuring the framebuffer surfaces.
|
||||||
|
@ -344,11 +340,6 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
|
BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
|
||||||
|
|
||||||
SyncViewport(surfaces_rect);
|
SyncViewport(surfaces_rect);
|
||||||
SyncBlendState();
|
|
||||||
SyncCullMode();
|
|
||||||
|
|
||||||
// TODO(bunnei): Sync framebuffer_scale uniform here
|
|
||||||
// TODO(bunnei): Sync scissorbox uniform(s) here
|
|
||||||
|
|
||||||
// Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
|
// Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
|
||||||
// scissor test to prevent drawing outside of the framebuffer region
|
// scissor test to prevent drawing outside of the framebuffer region
|
||||||
|
@ -359,6 +350,58 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
state.scissor.height = draw_rect.GetHeight();
|
state.scissor.height = draw_rect.GetHeight();
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
|
// Only return the surface to be marked as dirty if writing to it is enabled.
|
||||||
|
return std::make_pair(write_color_fb ? color_surface : nullptr,
|
||||||
|
write_depth_fb ? depth_surface : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::Clear() {
|
||||||
|
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
GLbitfield clear_mask = 0;
|
||||||
|
if (regs.clear_buffers.R && regs.clear_buffers.G && regs.clear_buffers.B &&
|
||||||
|
regs.clear_buffers.A) {
|
||||||
|
clear_mask |= GL_COLOR_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
if (regs.clear_buffers.Z)
|
||||||
|
clear_mask |= GL_DEPTH_BUFFER_BIT;
|
||||||
|
|
||||||
|
if (clear_mask == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
glClear(clear_mask);
|
||||||
|
|
||||||
|
// Mark framebuffer surfaces as dirty
|
||||||
|
if (dirty_color_surface != nullptr) {
|
||||||
|
res_cache.MarkSurfaceAsDirty(dirty_color_surface);
|
||||||
|
}
|
||||||
|
if (dirty_depth_surface != nullptr) {
|
||||||
|
res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerOpenGL::DrawArrays() {
|
||||||
|
if (accelerate_draw == AccelDraw::Disabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MICROPROFILE_SCOPE(OpenGL_Drawing);
|
||||||
|
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||||
|
|
||||||
|
auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
|
||||||
|
|
||||||
|
SyncBlendState();
|
||||||
|
SyncCullMode();
|
||||||
|
|
||||||
|
// TODO(bunnei): Sync framebuffer_scale uniform here
|
||||||
|
// TODO(bunnei): Sync scissorbox uniform(s) here
|
||||||
|
|
||||||
// Draw the vertex batch
|
// Draw the vertex batch
|
||||||
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
|
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
|
||||||
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
|
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
|
||||||
|
@ -439,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() {
|
||||||
state.Apply();
|
state.Apply();
|
||||||
|
|
||||||
// Mark framebuffer surfaces as dirty
|
// Mark framebuffer surfaces as dirty
|
||||||
if (color_surface != nullptr && write_color_fb) {
|
if (dirty_color_surface != nullptr) {
|
||||||
res_cache.MarkSurfaceAsDirty(color_surface);
|
res_cache.MarkSurfaceAsDirty(dirty_color_surface);
|
||||||
}
|
}
|
||||||
if (depth_surface != nullptr && write_depth_fb) {
|
if (dirty_depth_surface != nullptr) {
|
||||||
res_cache.MarkSurfaceAsDirty(depth_surface);
|
res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
@ -28,6 +29,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;
|
||||||
|
@ -81,6 +83,10 @@ private:
|
||||||
u32 border_color_a;
|
u32 border_color_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
|
||||||
|
/// surfaces if writing was enabled.
|
||||||
|
std::pair<Surface, Surface> ConfigureFramebuffers();
|
||||||
|
|
||||||
/// Binds the framebuffer color and depth surface
|
/// Binds the framebuffer color and depth surface
|
||||||
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
|
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
|
||||||
bool has_stencil);
|
bool has_stencil);
|
||||||
|
|
Loading…
Reference in a new issue