Merge pull request #2562 from ReinUsesLisp/split-cbuf-upload
video_core/engines: Move ConstBufferInfo out of Maxwell3D
This commit is contained in:
		@@ -3,6 +3,7 @@ add_library(video_core STATIC
 | 
			
		||||
    dma_pusher.h
 | 
			
		||||
    debug_utils/debug_utils.cpp
 | 
			
		||||
    debug_utils/debug_utils.h
 | 
			
		||||
    engines/const_buffer_info.h
 | 
			
		||||
    engines/engine_upload.cpp
 | 
			
		||||
    engines/engine_upload.h
 | 
			
		||||
    engines/fermi_2d.cpp
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/video_core/engines/const_buffer_info.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/video_core/engines/const_buffer_info.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
// Copyright 2019 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Tegra::Engines {
 | 
			
		||||
 | 
			
		||||
struct ConstBufferInfo {
 | 
			
		||||
    GPUVAddr address;
 | 
			
		||||
    u32 size;
 | 
			
		||||
    bool enabled;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Tegra::Engines
 | 
			
		||||
@@ -396,12 +396,10 @@ void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
 | 
			
		||||
    auto& shader = state.shader_stages[static_cast<std::size_t>(stage)];
 | 
			
		||||
    auto& bind_data = regs.cb_bind[static_cast<std::size_t>(stage)];
 | 
			
		||||
 | 
			
		||||
    ASSERT(bind_data.index < Regs::MaxConstBuffers);
 | 
			
		||||
    auto& buffer = shader.const_buffers[bind_data.index];
 | 
			
		||||
 | 
			
		||||
    ASSERT(bind_data.index < Regs::MaxConstBuffers);
 | 
			
		||||
 | 
			
		||||
    buffer.enabled = bind_data.valid.Value() != 0;
 | 
			
		||||
    buffer.index = bind_data.index;
 | 
			
		||||
    buffer.address = regs.const_buffer.BufferAddress();
 | 
			
		||||
    buffer.size = regs.const_buffer.cb_size;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@
 | 
			
		||||
#include "common/common_funcs.h"
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/math_util.h"
 | 
			
		||||
#include "video_core/engines/const_buffer_info.h"
 | 
			
		||||
#include "video_core/engines/engine_upload.h"
 | 
			
		||||
#include "video_core/gpu.h"
 | 
			
		||||
#include "video_core/macro_interpreter.h"
 | 
			
		||||
@@ -1112,13 +1113,6 @@ public:
 | 
			
		||||
    static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
 | 
			
		||||
 | 
			
		||||
    struct State {
 | 
			
		||||
        struct ConstBufferInfo {
 | 
			
		||||
            GPUVAddr address;
 | 
			
		||||
            u32 index;
 | 
			
		||||
            u32 size;
 | 
			
		||||
            bool enabled;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        struct ShaderStageInfo {
 | 
			
		||||
            std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers;
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -322,9 +322,9 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage);
 | 
			
		||||
        SetupConstBuffers(stage_enum, shader, program_handle, base_bindings);
 | 
			
		||||
        SetupGlobalRegions(stage_enum, shader, program_handle, base_bindings);
 | 
			
		||||
        SetupTextures(stage_enum, shader, program_handle, base_bindings);
 | 
			
		||||
        SetupDrawConstBuffers(stage_enum, shader);
 | 
			
		||||
        SetupGlobalRegions(stage_enum, shader);
 | 
			
		||||
        SetupTextures(stage_enum, shader, base_bindings);
 | 
			
		||||
 | 
			
		||||
        // Workaround for Intel drivers.
 | 
			
		||||
        // When a clip distance is enabled but not set in the shader it crops parts of the screen
 | 
			
		||||
@@ -776,57 +776,55 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
			
		||||
                                         const Shader& shader, GLuint program_handle,
 | 
			
		||||
                                         BaseBindings base_bindings) {
 | 
			
		||||
void RasterizerOpenGL::SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
			
		||||
                                             const Shader& shader) {
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_UBO);
 | 
			
		||||
    const auto& gpu = system.GPU();
 | 
			
		||||
    const auto& maxwell3d = gpu.Maxwell3D();
 | 
			
		||||
    const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
 | 
			
		||||
    const auto stage_index = static_cast<std::size_t>(stage);
 | 
			
		||||
    const auto& shader_stage = system.GPU().Maxwell3D().state.shader_stages[stage_index];
 | 
			
		||||
    const auto& entries = shader->GetShaderEntries().const_buffers;
 | 
			
		||||
 | 
			
		||||
    // Upload only the enabled buffers from the 16 constbuffers of each shader stage
 | 
			
		||||
    for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
 | 
			
		||||
        const auto& used_buffer = entries[bindpoint];
 | 
			
		||||
        const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
 | 
			
		||||
 | 
			
		||||
        if (!buffer.enabled) {
 | 
			
		||||
            // Set values to zero to unbind buffers
 | 
			
		||||
            bind_ubo_pushbuffer.Push(0, 0, 0);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::size_t size = 0;
 | 
			
		||||
 | 
			
		||||
        if (used_buffer.IsIndirect()) {
 | 
			
		||||
            // Buffer is accessed indirectly, so upload the entire thing
 | 
			
		||||
            size = buffer.size;
 | 
			
		||||
 | 
			
		||||
            if (size > MaxConstbufferSize) {
 | 
			
		||||
                LOG_WARNING(Render_OpenGL, "Indirect constbuffer size {} exceeds maximum {}", size,
 | 
			
		||||
                            MaxConstbufferSize);
 | 
			
		||||
                size = MaxConstbufferSize;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            // Buffer is accessed directly, upload just what we use
 | 
			
		||||
            size = used_buffer.GetSize();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Align the actual size so it ends up being a multiple of vec4 to meet the OpenGL std140
 | 
			
		||||
        // UBO alignment requirements.
 | 
			
		||||
        size = Common::AlignUp(size, sizeof(GLvec4));
 | 
			
		||||
        ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
 | 
			
		||||
 | 
			
		||||
        const GLintptr const_buffer_offset =
 | 
			
		||||
            buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment());
 | 
			
		||||
 | 
			
		||||
        bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size);
 | 
			
		||||
        const auto& entry = entries[bindpoint];
 | 
			
		||||
        SetupConstBuffer(shader_stage.const_buffers[entry.GetIndex()], entry);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& buffer,
 | 
			
		||||
                                        const GLShader::ConstBufferEntry& entry) {
 | 
			
		||||
    if (!buffer.enabled) {
 | 
			
		||||
        // Set values to zero to unbind buffers
 | 
			
		||||
        bind_ubo_pushbuffer.Push(0, 0, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::size_t size;
 | 
			
		||||
    if (entry.IsIndirect()) {
 | 
			
		||||
        // Buffer is accessed indirectly, so upload the entire thing
 | 
			
		||||
        size = buffer.size;
 | 
			
		||||
 | 
			
		||||
        if (size > MaxConstbufferSize) {
 | 
			
		||||
            LOG_WARNING(Render_OpenGL, "Indirect constbuffer size {} exceeds maximum {}", size,
 | 
			
		||||
                        MaxConstbufferSize);
 | 
			
		||||
            size = MaxConstbufferSize;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        // Buffer is accessed directly, upload just what we use
 | 
			
		||||
        size = entry.GetSize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Align the actual size so it ends up being a multiple of vec4 to meet the OpenGL std140
 | 
			
		||||
    // UBO alignment requirements.
 | 
			
		||||
    size = Common::AlignUp(size, sizeof(GLvec4));
 | 
			
		||||
    ASSERT_MSG(size <= MaxConstbufferSize, "Constant buffer is too big");
 | 
			
		||||
 | 
			
		||||
    const std::size_t alignment = device.GetUniformBufferAlignment();
 | 
			
		||||
    const GLintptr offset = buffer_cache.UploadMemory(buffer.address, size, alignment);
 | 
			
		||||
    bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), offset, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
			
		||||
                                          const Shader& shader, GLenum primitive_mode,
 | 
			
		||||
                                          BaseBindings base_bindings) {
 | 
			
		||||
                                          const Shader& shader) {
 | 
			
		||||
    const auto& entries = shader->GetShaderEntries().global_memory_entries;
 | 
			
		||||
    for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
 | 
			
		||||
        const auto& entry{entries[bindpoint]};
 | 
			
		||||
@@ -840,7 +838,7 @@ void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::Shade
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader,
 | 
			
		||||
                                     GLuint program_handle, BaseBindings base_bindings) {
 | 
			
		||||
                                     BaseBindings base_bindings) {
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_Texture);
 | 
			
		||||
    const auto& gpu = system.GPU();
 | 
			
		||||
    const auto& maxwell3d = gpu.Maxwell3D();
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include <glad/glad.h>
 | 
			
		||||
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "video_core/engines/const_buffer_info.h"
 | 
			
		||||
#include "video_core/engines/maxwell_3d.h"
 | 
			
		||||
#include "video_core/rasterizer_cache.h"
 | 
			
		||||
#include "video_core/rasterizer_interface.h"
 | 
			
		||||
@@ -27,6 +28,7 @@
 | 
			
		||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_sampler_cache.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_cache.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
 | 
			
		||||
#include "video_core/renderer_opengl/gl_state.h"
 | 
			
		||||
#include "video_core/renderer_opengl/utils.h"
 | 
			
		||||
@@ -105,17 +107,20 @@ private:
 | 
			
		||||
        bool preserve_contents = true, std::optional<std::size_t> single_color_target = {});
 | 
			
		||||
 | 
			
		||||
    /// Configures the current constbuffers to use for the draw command.
 | 
			
		||||
    void SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
 | 
			
		||||
                           GLuint program_handle, BaseBindings base_bindings);
 | 
			
		||||
    void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
			
		||||
                               const Shader& shader);
 | 
			
		||||
 | 
			
		||||
    /// Configures a constant buffer.
 | 
			
		||||
    void SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& buffer,
 | 
			
		||||
                          const GLShader::ConstBufferEntry& entry);
 | 
			
		||||
 | 
			
		||||
    /// Configures the current global memory entries to use for the draw command.
 | 
			
		||||
    void SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
 | 
			
		||||
                            const Shader& shader, GLenum primitive_mode,
 | 
			
		||||
                            BaseBindings base_bindings);
 | 
			
		||||
                            const Shader& shader);
 | 
			
		||||
 | 
			
		||||
    /// Configures the current textures to use for the draw command.
 | 
			
		||||
    void SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
 | 
			
		||||
                       GLuint program_handle, BaseBindings base_bindings);
 | 
			
		||||
                       BaseBindings base_bindings);
 | 
			
		||||
 | 
			
		||||
    /// Syncs the viewport and depth range to match the guest state
 | 
			
		||||
    void SyncViewport(OpenGLState& current_state);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user