1
1
Fork 0
forked from suyu/suyu

GPU: Only configure the used framebuffers during clear.

Don't try to configure the color buffer if it is not being cleared, it may not be completely valid at this point.
This commit is contained in:
Subv 2018-07-03 22:32:59 -05:00
parent c996787d84
commit 5a9df3c675
4 changed files with 48 additions and 17 deletions

View file

@ -297,7 +297,8 @@ bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
return true;
}
std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb,
bool using_depth_fb) {
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
// Sync the depth test state before configuring the framebuffer surfaces.
@ -306,9 +307,6 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
// TODO(bunnei): Implement this
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 =
@ -358,18 +356,25 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers() {
void RasterizerOpenGL::Clear() {
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
bool use_color_fb = false;
bool use_depth_fb = false;
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;
use_color_fb = true;
}
if (regs.clear_buffers.Z)
if (regs.clear_buffers.Z) {
clear_mask |= GL_DEPTH_BUFFER_BIT;
use_depth_fb = true;
}
if (clear_mask == 0)
return;
auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
auto [dirty_color_surface, dirty_depth_surface] =
ConfigureFramebuffers(use_color_fb, use_depth_fb);
// TODO(Subv): Support clearing only partial colors.
glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2],
@ -394,7 +399,8 @@ void RasterizerOpenGL::DrawArrays() {
MICROPROFILE_SCOPE(OpenGL_Drawing);
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
auto [dirty_color_surface, dirty_depth_surface] = ConfigureFramebuffers();
auto [dirty_color_surface, dirty_depth_surface] =
ConfigureFramebuffers(true, regs.zeta.Address() != 0);
SyncBlendState();
SyncCullMode();

View file

@ -85,7 +85,7 @@ private:
/// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
/// surfaces if writing was enabled.
std::pair<Surface, Surface> ConfigureFramebuffers();
std::pair<Surface, Surface> ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb);
/// Binds the framebuffer color and depth surface
void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,

View file

@ -65,6 +65,25 @@ struct FormatTuple {
return params;
}
/*static*/ SurfaceParams SurfaceParams::CreateForDepthBuffer(
const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config, Tegra::GPUVAddr zeta_address,
Tegra::DepthFormat format) {
SurfaceParams params{};
params.addr = zeta_address;
params.is_tiled = true;
params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
params.pixel_format = PixelFormatFromDepthFormat(format);
params.component_type = ComponentTypeFromDepthFormat(format);
params.type = GetFormatType(params.pixel_format);
params.size_in_bytes = params.SizeInBytes();
params.width = config.width;
params.height = config.height;
params.unaligned_height = config.height;
params.size_in_bytes = params.SizeInBytes();
return params;
}
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, ComponentType::UNorm, false}, // ABGR8
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, ComponentType::UNorm, false}, // B5G6R5
@ -461,15 +480,16 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
LOG_WARNING(Render_OpenGL, "hard-coded for render target 0!");
// get color and depth surfaces
const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(regs.rt[0])};
SurfaceParams depth_params{color_params};
SurfaceParams color_params{};
SurfaceParams depth_params{};
if (using_color_fb) {
color_params = SurfaceParams::CreateForFramebuffer(regs.rt[0]);
}
if (using_depth_fb) {
depth_params.addr = regs.zeta.Address();
depth_params.pixel_format = SurfaceParams::PixelFormatFromDepthFormat(regs.zeta.format);
depth_params.component_type = SurfaceParams::ComponentTypeFromDepthFormat(regs.zeta.format);
depth_params.type = SurfaceParams::GetFormatType(depth_params.pixel_format);
depth_params.size_in_bytes = depth_params.SizeInBytes();
depth_params =
SurfaceParams::CreateForDepthBuffer(regs.rt[0], regs.zeta.Address(), regs.zeta.format);
}
MathUtil::Rectangle<u32> color_rect{};

View file

@ -326,13 +326,18 @@ struct SurfaceParams {
return addr <= (region_addr + region_size) && region_addr <= (addr + size_in_bytes);
}
/// Creates SurfaceParams from a texture configation
/// Creates SurfaceParams from a texture configuration
static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
/// Creates SurfaceParams from a framebuffer configation
/// Creates SurfaceParams from a framebuffer configuration
static SurfaceParams CreateForFramebuffer(
const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
/// Creates SurfaceParams for a depth buffer configuration
static SurfaceParams CreateForDepthBuffer(
const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config,
Tegra::GPUVAddr zeta_address, Tegra::DepthFormat format);
Tegra::GPUVAddr addr;
bool is_tiled;
u32 block_height;