Merge pull request #2562 from ReinUsesLisp/split-cbuf-upload
video_core/engines: Move ConstBufferInfo out of Maxwell3D
This commit is contained in:
commit
c7b5c245e1
6 changed files with 74 additions and 61 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue