mirror of
				https://github.com/yuzu-emu/yuzu.git
				synced 2025-11-04 12:33:43 +00:00 
			
		
		
		
	Merge pull request #1824 from ReinUsesLisp/fbcache
gl_rasterizer: Implement a framebuffer cache
This commit is contained in:
		
						commit
						9390452195
					
				@ -79,6 +79,26 @@ struct DrawParameters {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct FramebufferCacheKey {
 | 
			
		||||
    bool is_single_buffer = false;
 | 
			
		||||
    bool stencil_enable = false;
 | 
			
		||||
 | 
			
		||||
    std::array<GLenum, Maxwell::NumRenderTargets> color_attachments{};
 | 
			
		||||
    std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> colors{};
 | 
			
		||||
    u32 colors_count = 0;
 | 
			
		||||
 | 
			
		||||
    GLuint zeta = 0;
 | 
			
		||||
 | 
			
		||||
    auto Tie() const {
 | 
			
		||||
        return std::tie(is_single_buffer, stencil_enable, color_attachments, colors, colors_count,
 | 
			
		||||
                        zeta);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator<(const FramebufferCacheKey& rhs) const {
 | 
			
		||||
        return Tie() < rhs.Tie();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo& info)
 | 
			
		||||
    : res_cache{*this}, shader_cache{*this}, emu_window{window}, screen_info{info},
 | 
			
		||||
      buffer_cache(*this, STREAM_BUFFER_SIZE) {
 | 
			
		||||
@ -90,9 +110,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo
 | 
			
		||||
 | 
			
		||||
    OpenGLState::ApplyDefaultState();
 | 
			
		||||
 | 
			
		||||
    // Create render framebuffer
 | 
			
		||||
    framebuffer.Create();
 | 
			
		||||
 | 
			
		||||
    shader_program_manager = std::make_unique<GLShader::ProgramManager>();
 | 
			
		||||
    state.draw.shader_program = 0;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
@ -361,6 +378,44 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
			
		||||
    SyncClipEnabled(clip_distances);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupCachedFramebuffer(const FramebufferCacheKey& fbkey,
 | 
			
		||||
                                              OpenGLState& current_state) {
 | 
			
		||||
    const auto [entry, is_cache_miss] = framebuffer_cache.try_emplace(fbkey);
 | 
			
		||||
    auto& framebuffer = entry->second;
 | 
			
		||||
 | 
			
		||||
    if (is_cache_miss)
 | 
			
		||||
        framebuffer.Create();
 | 
			
		||||
 | 
			
		||||
    current_state.draw.draw_framebuffer = framebuffer.handle;
 | 
			
		||||
    current_state.ApplyFramebufferState();
 | 
			
		||||
 | 
			
		||||
    if (!is_cache_miss)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (fbkey.is_single_buffer) {
 | 
			
		||||
        if (fbkey.color_attachments[0] != GL_NONE) {
 | 
			
		||||
            glFramebufferTexture(GL_DRAW_FRAMEBUFFER, fbkey.color_attachments[0], fbkey.colors[0],
 | 
			
		||||
                                 0);
 | 
			
		||||
        }
 | 
			
		||||
        glDrawBuffer(fbkey.color_attachments[0]);
 | 
			
		||||
    } else {
 | 
			
		||||
        for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
 | 
			
		||||
            if (fbkey.colors[index]) {
 | 
			
		||||
                glFramebufferTexture(GL_DRAW_FRAMEBUFFER,
 | 
			
		||||
                                     GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
 | 
			
		||||
                                     fbkey.colors[index], 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        glDrawBuffers(fbkey.colors_count, fbkey.color_attachments.data());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fbkey.zeta) {
 | 
			
		||||
        GLenum zeta_attachment =
 | 
			
		||||
            fbkey.stencil_enable ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
 | 
			
		||||
        glFramebufferTexture(GL_DRAW_FRAMEBUFFER, zeta_attachment, fbkey.zeta, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const {
 | 
			
		||||
    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
 | 
			
		||||
 | 
			
		||||
@ -444,10 +499,10 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
 | 
			
		||||
    UNIMPLEMENTED_IF(regs.rt_separate_frag_data != 0);
 | 
			
		||||
 | 
			
		||||
    // Bind the framebuffer surfaces
 | 
			
		||||
    current_state.draw.draw_framebuffer = framebuffer.handle;
 | 
			
		||||
    current_state.ApplyFramebufferState();
 | 
			
		||||
    current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0;
 | 
			
		||||
 | 
			
		||||
    FramebufferCacheKey fbkey;
 | 
			
		||||
 | 
			
		||||
    if (using_color_fb) {
 | 
			
		||||
        if (single_color_target) {
 | 
			
		||||
            // Used when just a single color attachment is enabled, e.g. for clearing a color buffer
 | 
			
		||||
@ -463,14 +518,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
 | 
			
		||||
                state.framebuffer_srgb.enabled |= color_surface->GetSurfaceParams().srgb_conversion;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            glFramebufferTexture2D(
 | 
			
		||||
                GL_DRAW_FRAMEBUFFER,
 | 
			
		||||
                GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D,
 | 
			
		||||
                color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
 | 
			
		||||
            glDrawBuffer(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target));
 | 
			
		||||
            fbkey.is_single_buffer = true;
 | 
			
		||||
            fbkey.color_attachments[0] =
 | 
			
		||||
                GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target);
 | 
			
		||||
            fbkey.colors[0] = color_surface != nullptr ? color_surface->Texture().handle : 0;
 | 
			
		||||
        } else {
 | 
			
		||||
            // Multiple color attachments are enabled
 | 
			
		||||
            std::array<GLenum, Maxwell::NumRenderTargets> buffers;
 | 
			
		||||
            for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
 | 
			
		||||
                Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
 | 
			
		||||
 | 
			
		||||
@ -485,22 +538,17 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
 | 
			
		||||
                        color_surface->GetSurfaceParams().srgb_conversion;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
                fbkey.color_attachments[index] =
 | 
			
		||||
                    GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
 | 
			
		||||
                fbkey.colors[index] =
 | 
			
		||||
                    color_surface != nullptr ? color_surface->Texture().handle : 0;
 | 
			
		||||
            }
 | 
			
		||||
            glDrawBuffers(regs.rt_control.count, buffers.data());
 | 
			
		||||
            fbkey.is_single_buffer = false;
 | 
			
		||||
            fbkey.colors_count = regs.rt_control.count;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // No color attachments are enabled - zero out all of them
 | 
			
		||||
        for (std::size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
 | 
			
		||||
            glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
 | 
			
		||||
                                   GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D,
 | 
			
		||||
                                   0, 0);
 | 
			
		||||
        }
 | 
			
		||||
        glDrawBuffer(GL_NONE);
 | 
			
		||||
        // No color attachments are enabled - leave them as zero
 | 
			
		||||
        fbkey.is_single_buffer = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (depth_surface) {
 | 
			
		||||
@ -508,22 +556,12 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
 | 
			
		||||
        // the shader doesn't actually write to it.
 | 
			
		||||
        depth_surface->MarkAsModified(true, res_cache);
 | 
			
		||||
 | 
			
		||||
        if (regs.stencil_enable) {
 | 
			
		||||
            // 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);
 | 
			
		||||
        fbkey.zeta = depth_surface->Texture().handle;
 | 
			
		||||
        fbkey.stencil_enable = regs.stencil_enable;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SetupCachedFramebuffer(fbkey, current_state);
 | 
			
		||||
 | 
			
		||||
    SyncViewport(current_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ namespace OpenGL {
 | 
			
		||||
 | 
			
		||||
struct ScreenInfo;
 | 
			
		||||
struct DrawParameters;
 | 
			
		||||
struct FramebufferCacheKey;
 | 
			
		||||
 | 
			
		||||
class RasterizerOpenGL : public VideoCore::RasterizerInterface {
 | 
			
		||||
public:
 | 
			
		||||
@ -195,11 +196,12 @@ private:
 | 
			
		||||
             OGLVertexArray>
 | 
			
		||||
        vertex_array_cache;
 | 
			
		||||
 | 
			
		||||
    std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache;
 | 
			
		||||
 | 
			
		||||
    std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
 | 
			
		||||
    OGLBufferCache buffer_cache;
 | 
			
		||||
    OGLFramebuffer framebuffer;
 | 
			
		||||
    PrimitiveAssembler primitive_assembler{buffer_cache};
 | 
			
		||||
    GLint uniform_buffer_alignment;
 | 
			
		||||
 | 
			
		||||
@ -214,6 +216,8 @@ private:
 | 
			
		||||
 | 
			
		||||
    void SetupShaders(GLenum primitive_mode);
 | 
			
		||||
 | 
			
		||||
    void SetupCachedFramebuffer(const FramebufferCacheKey& fbkey, OpenGLState& current_state);
 | 
			
		||||
 | 
			
		||||
    enum class AccelDraw { Disabled, Arrays, Indexed };
 | 
			
		||||
    AccelDraw accelerate_draw = AccelDraw::Disabled;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user