mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1281 from bunnei/multi-rt
gl_rasterizer: Implement multiple color attachments.
This commit is contained in:
		
						commit
						ac959799e4
					
				@ -533,7 +533,11 @@ public:
 | 
				
			|||||||
                u32 stencil_back_mask;
 | 
					                u32 stencil_back_mask;
 | 
				
			||||||
                u32 stencil_back_func_mask;
 | 
					                u32 stencil_back_func_mask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                INSERT_PADDING_WORDS(0x20);
 | 
					                INSERT_PADDING_WORDS(0x13);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                u32 rt_separate_frag_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                INSERT_PADDING_WORDS(0xC);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                struct {
 | 
					                struct {
 | 
				
			||||||
                    u32 address_high;
 | 
					                    u32 address_high;
 | 
				
			||||||
@ -557,7 +561,22 @@ public:
 | 
				
			|||||||
                struct {
 | 
					                struct {
 | 
				
			||||||
                    union {
 | 
					                    union {
 | 
				
			||||||
                        BitField<0, 4, u32> count;
 | 
					                        BitField<0, 4, u32> count;
 | 
				
			||||||
 | 
					                        BitField<4, 3, u32> map_0;
 | 
				
			||||||
 | 
					                        BitField<7, 3, u32> map_1;
 | 
				
			||||||
 | 
					                        BitField<10, 3, u32> map_2;
 | 
				
			||||||
 | 
					                        BitField<13, 3, u32> map_3;
 | 
				
			||||||
 | 
					                        BitField<16, 3, u32> map_4;
 | 
				
			||||||
 | 
					                        BitField<19, 3, u32> map_5;
 | 
				
			||||||
 | 
					                        BitField<22, 3, u32> map_6;
 | 
				
			||||||
 | 
					                        BitField<25, 3, u32> map_7;
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    u32 GetMap(size_t index) const {
 | 
				
			||||||
 | 
					                        const std::array<u32, NumRenderTargets> maps{map_0, map_1, map_2, map_3,
 | 
				
			||||||
 | 
					                                                                     map_4, map_5, map_6, map_7};
 | 
				
			||||||
 | 
					                        ASSERT(index < maps.size());
 | 
				
			||||||
 | 
					                        return maps[index];
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } rt_control;
 | 
					                } rt_control;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                INSERT_PADDING_WORDS(0x2);
 | 
					                INSERT_PADDING_WORDS(0x2);
 | 
				
			||||||
@ -968,6 +987,7 @@ ASSERT_REG_POSITION(clear_stencil, 0x368);
 | 
				
			|||||||
ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
 | 
					ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
 | 
				
			||||||
ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
 | 
					ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
 | 
				
			||||||
ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
 | 
					ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
 | 
				
			||||||
 | 
					ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
 | 
				
			||||||
ASSERT_REG_POSITION(zeta, 0x3F8);
 | 
					ASSERT_REG_POSITION(zeta, 0x3F8);
 | 
				
			||||||
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
 | 
					ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
 | 
				
			||||||
ASSERT_REG_POSITION(rt_control, 0x487);
 | 
					ASSERT_REG_POSITION(rt_control, 0x487);
 | 
				
			||||||
 | 
				
			|||||||
@ -294,17 +294,10 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
 | 
				
			|||||||
        cached_pages.add({pages_interval, delta});
 | 
					        cached_pages.add({pages_interval, delta});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb,
 | 
					void RasterizerOpenGL::ConfigureFramebuffers(bool using_depth_fb, bool preserve_contents) {
 | 
				
			||||||
                                                                    bool using_depth_fb,
 | 
					 | 
				
			||||||
                                                                    bool preserve_contents) {
 | 
					 | 
				
			||||||
    MICROPROFILE_SCOPE(OpenGL_Framebuffer);
 | 
					    MICROPROFILE_SCOPE(OpenGL_Framebuffer);
 | 
				
			||||||
    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
					    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (regs.rt[0].format == Tegra::RenderTargetFormat::NONE) {
 | 
					 | 
				
			||||||
        LOG_ERROR(HW_GPU, "RenderTargetFormat is not configured");
 | 
					 | 
				
			||||||
        using_color_fb = false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const bool has_stencil = regs.stencil_enable;
 | 
					    const bool has_stencil = regs.stencil_enable;
 | 
				
			||||||
    const bool write_color_fb =
 | 
					    const bool write_color_fb =
 | 
				
			||||||
        state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
 | 
					        state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE ||
 | 
				
			||||||
@ -314,41 +307,52 @@ std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_c
 | 
				
			|||||||
        (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
 | 
					        (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
 | 
				
			||||||
        (has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
 | 
					        (has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Surface color_surface;
 | 
					 | 
				
			||||||
    Surface depth_surface;
 | 
					    Surface depth_surface;
 | 
				
			||||||
    MathUtil::Rectangle<u32> surfaces_rect;
 | 
					    if (using_depth_fb) {
 | 
				
			||||||
    std::tie(color_surface, depth_surface, surfaces_rect) =
 | 
					        depth_surface = res_cache.GetDepthBufferSurface(preserve_contents);
 | 
				
			||||||
        res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, preserve_contents);
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
 | 
					    // TODO(bunnei): Figure out how the below register works. According to envytools, this should be
 | 
				
			||||||
    const MathUtil::Rectangle<u32> draw_rect{
 | 
					    // used to enable multiple render targets. However, it is left unset on all games that I have
 | 
				
			||||||
        static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left,
 | 
					    // tested.
 | 
				
			||||||
                                         surfaces_rect.left, surfaces_rect.right)), // Left
 | 
					    ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
 | 
				
			||||||
        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
 | 
					    // Bind the framebuffer surfaces
 | 
				
			||||||
    BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
 | 
					    state.draw.draw_framebuffer = framebuffer.handle;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    SyncViewport(surfaces_rect);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 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();
 | 
					    state.Apply();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Only return the surface to be marked as dirty if writing to it is enabled.
 | 
					    std::array<GLenum, Maxwell::NumRenderTargets> buffers;
 | 
				
			||||||
    return std::make_pair(write_color_fb ? color_surface : nullptr,
 | 
					    for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
 | 
				
			||||||
                          write_depth_fb ? depth_surface : nullptr);
 | 
					        Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
 | 
				
			||||||
 | 
					        buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
 | 
				
			||||||
 | 
					        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
 | 
				
			||||||
 | 
					                               GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D,
 | 
				
			||||||
 | 
					                               color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glDrawBuffers(regs.rt_control.count, buffers.data());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (depth_surface) {
 | 
				
			||||||
 | 
					        if (has_stencil) {
 | 
				
			||||||
 | 
					            // Attach both depth and stencil
 | 
				
			||||||
 | 
					            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
 | 
				
			||||||
 | 
					                                   depth_surface->Texture().handle, 0);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            // Attach depth
 | 
				
			||||||
 | 
					            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
 | 
				
			||||||
 | 
					                                   depth_surface->Texture().handle, 0);
 | 
				
			||||||
 | 
					            // Clear stencil attachment
 | 
				
			||||||
 | 
					            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // Clear both depth and stencil attachment
 | 
				
			||||||
 | 
					        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
 | 
				
			||||||
 | 
					                               0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SyncViewport();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    state.Apply();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::Clear() {
 | 
					void RasterizerOpenGL::Clear() {
 | 
				
			||||||
@ -407,8 +411,7 @@ void RasterizerOpenGL::Clear() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ScopeAcquireGLContext acquire_context{emu_window};
 | 
					    ScopeAcquireGLContext acquire_context{emu_window};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto [dirty_color_surface, dirty_depth_surface] =
 | 
					    ConfigureFramebuffers(use_depth_fb, false);
 | 
				
			||||||
        ConfigureFramebuffers(use_color_fb, use_depth_fb, false);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    clear_state.Apply();
 | 
					    clear_state.Apply();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -430,8 +433,7 @@ void RasterizerOpenGL::DrawArrays() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ScopeAcquireGLContext acquire_context{emu_window};
 | 
					    ScopeAcquireGLContext acquire_context{emu_window};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto [dirty_color_surface, dirty_depth_surface] =
 | 
					    ConfigureFramebuffers(true, true);
 | 
				
			||||||
        ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SyncDepthTestState();
 | 
					    SyncDepthTestState();
 | 
				
			||||||
    SyncStencilTestState();
 | 
					    SyncStencilTestState();
 | 
				
			||||||
@ -729,38 +731,12 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
 | 
				
			|||||||
    return current_unit + static_cast<u32>(entries.size());
 | 
					    return current_unit + static_cast<u32>(entries.size());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
 | 
					void RasterizerOpenGL::SyncViewport() {
 | 
				
			||||||
                                               const Surface& depth_surface, bool has_stencil) {
 | 
					 | 
				
			||||||
    state.draw.draw_framebuffer = framebuffer.handle;
 | 
					 | 
				
			||||||
    state.Apply();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
 | 
					 | 
				
			||||||
                           color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
 | 
					 | 
				
			||||||
    if (depth_surface != nullptr) {
 | 
					 | 
				
			||||||
        if (has_stencil) {
 | 
					 | 
				
			||||||
            // attach both depth and stencil
 | 
					 | 
				
			||||||
            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
 | 
					 | 
				
			||||||
                                   depth_surface->Texture().handle, 0);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // attach depth
 | 
					 | 
				
			||||||
            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
 | 
					 | 
				
			||||||
                                   depth_surface->Texture().handle, 0);
 | 
					 | 
				
			||||||
            // clear stencil attachment
 | 
					 | 
				
			||||||
            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        // clear both depth and stencil attachment
 | 
					 | 
				
			||||||
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
 | 
					 | 
				
			||||||
                               0);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void RasterizerOpenGL::SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect) {
 | 
					 | 
				
			||||||
    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
					    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
				
			||||||
    const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
 | 
					    const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state.viewport.x = static_cast<GLint>(surfaces_rect.left) + viewport_rect.left;
 | 
					    state.viewport.x = viewport_rect.left;
 | 
				
			||||||
    state.viewport.y = static_cast<GLint>(surfaces_rect.bottom) + viewport_rect.bottom;
 | 
					    state.viewport.y = viewport_rect.bottom;
 | 
				
			||||||
    state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
 | 
					    state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
 | 
				
			||||||
    state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
 | 
					    state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -97,14 +97,8 @@ private:
 | 
				
			|||||||
        GLvec4 border_color;
 | 
					        GLvec4 border_color;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth>
 | 
					    /// Configures the color and depth framebuffer states
 | 
				
			||||||
    /// surfaces if writing was enabled.
 | 
					    void ConfigureFramebuffers(bool using_depth_fb, bool preserve_contents);
 | 
				
			||||||
    std::pair<Surface, Surface> ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
 | 
					 | 
				
			||||||
                                                      bool preserve_contents);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Binds the framebuffer color and depth surface
 | 
					 | 
				
			||||||
    void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface,
 | 
					 | 
				
			||||||
                                 bool has_stencil);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Configures the current constbuffers to use for the draw command.
 | 
					     * Configures the current constbuffers to use for the draw command.
 | 
				
			||||||
@ -127,7 +121,7 @@ private:
 | 
				
			|||||||
                      u32 current_unit);
 | 
					                      u32 current_unit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Syncs the viewport to match the guest state
 | 
					    /// Syncs the viewport to match the guest state
 | 
				
			||||||
    void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect);
 | 
					    void SyncViewport();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Syncs the clip enabled status to match the guest state
 | 
					    /// Syncs the clip enabled status to match the guest state
 | 
				
			||||||
    void SyncClipEnabled();
 | 
					    void SyncClipEnabled();
 | 
				
			||||||
 | 
				
			|||||||
@ -61,8 +61,8 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
 | 
				
			|||||||
    return params;
 | 
					    return params;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer(
 | 
					/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer(size_t index) {
 | 
				
			||||||
    const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config) {
 | 
					    const auto& config{Core::System::GetInstance().GPU().Maxwell3D().regs.rt[index]};
 | 
				
			||||||
    SurfaceParams params{};
 | 
					    SurfaceParams params{};
 | 
				
			||||||
    params.addr = TryGetCpuAddr(config.Address());
 | 
					    params.addr = TryGetCpuAddr(config.Address());
 | 
				
			||||||
    params.is_tiled = true;
 | 
					    params.is_tiled = true;
 | 
				
			||||||
@ -708,62 +708,34 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
 | 
				
			|||||||
    return GetSurface(SurfaceParams::CreateForTexture(config));
 | 
					    return GetSurface(SurfaceParams::CreateForTexture(config));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool using_color_fb,
 | 
					Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) {
 | 
				
			||||||
                                                                       bool using_depth_fb,
 | 
					    const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs};
 | 
				
			||||||
                                                                       bool preserve_contents) {
 | 
					    if (!regs.zeta.Address() || !regs.zeta_enable) {
 | 
				
			||||||
    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
					        return {};
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO(bunnei): This is hard corded to use just the first render buffer
 | 
					 | 
				
			||||||
    LOG_TRACE(Render_OpenGL, "hard-coded for render target 0!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // get color and depth surfaces
 | 
					 | 
				
			||||||
    SurfaceParams color_params{};
 | 
					 | 
				
			||||||
    SurfaceParams depth_params{};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (using_color_fb) {
 | 
					 | 
				
			||||||
        color_params = SurfaceParams::CreateForFramebuffer(regs.rt[0]);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (using_depth_fb) {
 | 
					    SurfaceParams depth_params{SurfaceParams::CreateForDepthBuffer(
 | 
				
			||||||
        depth_params = SurfaceParams::CreateForDepthBuffer(regs.zeta_width, regs.zeta_height,
 | 
					        regs.zeta_width, regs.zeta_height, regs.zeta.Address(), regs.zeta.format)};
 | 
				
			||||||
                                                           regs.zeta.Address(), regs.zeta.format);
 | 
					
 | 
				
			||||||
 | 
					    return GetSurface(depth_params, preserve_contents);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Surface RasterizerCacheOpenGL::GetColorBufferSurface(size_t index, bool preserve_contents) {
 | 
				
			||||||
 | 
					    const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (index >= regs.rt_control.count) {
 | 
				
			||||||
 | 
					        return {};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MathUtil::Rectangle<u32> color_rect{};
 | 
					    if (regs.rt[index].Address() == 0 || regs.rt[index].format == Tegra::RenderTargetFormat::NONE) {
 | 
				
			||||||
    Surface color_surface;
 | 
					        return {};
 | 
				
			||||||
    if (using_color_fb) {
 | 
					 | 
				
			||||||
        color_surface = GetSurface(color_params, preserve_contents);
 | 
					 | 
				
			||||||
        if (color_surface) {
 | 
					 | 
				
			||||||
            color_rect = color_surface->GetSurfaceParams().GetRect();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MathUtil::Rectangle<u32> depth_rect{};
 | 
					    const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(index)};
 | 
				
			||||||
    Surface depth_surface;
 | 
					 | 
				
			||||||
    if (using_depth_fb) {
 | 
					 | 
				
			||||||
        depth_surface = GetSurface(depth_params, preserve_contents);
 | 
					 | 
				
			||||||
        if (depth_surface) {
 | 
					 | 
				
			||||||
            depth_rect = depth_surface->GetSurfaceParams().GetRect();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MathUtil::Rectangle<u32> fb_rect{};
 | 
					    return GetSurface(color_params, preserve_contents);
 | 
				
			||||||
    if (color_surface && depth_surface) {
 | 
					 | 
				
			||||||
        fb_rect = color_rect;
 | 
					 | 
				
			||||||
        // Color and Depth surfaces must have the same dimensions and offsets
 | 
					 | 
				
			||||||
        if (color_rect.bottom != depth_rect.bottom || color_rect.top != depth_rect.top ||
 | 
					 | 
				
			||||||
            color_rect.left != depth_rect.left || color_rect.right != depth_rect.right) {
 | 
					 | 
				
			||||||
            color_surface = GetSurface(color_params);
 | 
					 | 
				
			||||||
            depth_surface = GetSurface(depth_params);
 | 
					 | 
				
			||||||
            fb_rect = color_surface->GetSurfaceParams().GetRect();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else if (color_surface) {
 | 
					 | 
				
			||||||
        fb_rect = color_rect;
 | 
					 | 
				
			||||||
    } else if (depth_surface) {
 | 
					 | 
				
			||||||
        fb_rect = depth_rect;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return std::make_tuple(color_surface, depth_surface, fb_rect);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
 | 
					void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
 | 
				
			||||||
 | 
				
			|||||||
@ -669,8 +669,7 @@ struct SurfaceParams {
 | 
				
			|||||||
    static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
 | 
					    static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates SurfaceParams from a framebuffer configuration
 | 
					    /// Creates SurfaceParams from a framebuffer configuration
 | 
				
			||||||
    static SurfaceParams CreateForFramebuffer(
 | 
					    static SurfaceParams CreateForFramebuffer(size_t index);
 | 
				
			||||||
        const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates SurfaceParams for a depth buffer configuration
 | 
					    /// Creates SurfaceParams for a depth buffer configuration
 | 
				
			||||||
    static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height,
 | 
					    static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height,
 | 
				
			||||||
@ -774,9 +773,11 @@ public:
 | 
				
			|||||||
    /// Get a surface based on the texture configuration
 | 
					    /// Get a surface based on the texture configuration
 | 
				
			||||||
    Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config);
 | 
					    Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Get the color and depth surfaces based on the framebuffer configuration
 | 
					    /// Get the depth surface based on the framebuffer configuration
 | 
				
			||||||
    SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb,
 | 
					    Surface GetDepthBufferSurface(bool preserve_contents);
 | 
				
			||||||
                                                    bool preserve_contents);
 | 
					
 | 
				
			||||||
 | 
					    /// Get the color surface based on the framebuffer configuration and the specified render target
 | 
				
			||||||
 | 
					    Surface GetColorBufferSurface(size_t index, bool preserve_contents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Flushes the surface to Switch memory
 | 
					    /// Flushes the surface to Switch memory
 | 
				
			||||||
    void FlushSurface(const Surface& surface);
 | 
					    void FlushSurface(const Surface& surface);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user