Merge pull request #609 from Subv/clear_buffers

GPU: Implemented the CLEAR_BUFFERS register.
This commit is contained in:
bunnei 2018-07-03 19:34:34 -04:00 committed by GitHub
commit c996787d84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 105 additions and 16 deletions

View file

@ -297,11 +297,7 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
return true;
}
void RasterizerOpenGL::DrawArrays() {
if (accelerate_draw == AccelDraw::Disabled)
return;
MICROPROFILE_SCOPE(OpenGL_Drawing);
std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
// Sync the depth test state before configuring the framebuffer surfaces.
@ -344,11 +340,6 @@ void RasterizerOpenGL::DrawArrays() {
BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
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
// scissor test to prevent drawing outside of the framebuffer region
@ -359,6 +350,58 @@ void RasterizerOpenGL::DrawArrays() {
state.scissor.height = draw_rect.GetHeight();
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
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
@ -439,11 +482,11 @@ void RasterizerOpenGL::DrawArrays() {
state.Apply();
// Mark framebuffer surfaces as dirty
if (color_surface != nullptr && write_color_fb) {
res_cache.MarkSurfaceAsDirty(color_surface);
if (dirty_color_surface != nullptr) {
res_cache.MarkSurfaceAsDirty(dirty_color_surface);
}
if (depth_surface != nullptr && write_depth_fb) {
res_cache.MarkSurfaceAsDirty(depth_surface);
if (dirty_depth_surface != nullptr) {
res_cache.MarkSurfaceAsDirty(dirty_depth_surface);
}
}

View file

@ -7,6 +7,7 @@
#include <array>
#include <cstddef>
#include <memory>
#include <utility>
#include <vector>
#include <glad/glad.h>
#include "common/common_types.h"
@ -28,6 +29,7 @@ public:
~RasterizerOpenGL() override;
void DrawArrays() override;
void Clear() override;
void NotifyMaxwellRegisterChanged(u32 method) override;
void FlushAll() override;
void FlushRegion(Tegra::GPUVAddr addr, u64 size) override;
@ -81,6 +83,10 @@ private:
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
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
bool has_stencil);