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
|
dma_pusher.h
|
||||||
debug_utils/debug_utils.cpp
|
debug_utils/debug_utils.cpp
|
||||||
debug_utils/debug_utils.h
|
debug_utils/debug_utils.h
|
||||||
|
engines/const_buffer_info.h
|
||||||
engines/engine_upload.cpp
|
engines/engine_upload.cpp
|
||||||
engines/engine_upload.h
|
engines/engine_upload.h
|
||||||
engines/fermi_2d.cpp
|
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& shader = state.shader_stages[static_cast<std::size_t>(stage)];
|
||||||
auto& bind_data = regs.cb_bind[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];
|
auto& buffer = shader.const_buffers[bind_data.index];
|
||||||
|
|
||||||
ASSERT(bind_data.index < Regs::MaxConstBuffers);
|
|
||||||
|
|
||||||
buffer.enabled = bind_data.valid.Value() != 0;
|
buffer.enabled = bind_data.valid.Value() != 0;
|
||||||
buffer.index = bind_data.index;
|
|
||||||
buffer.address = regs.const_buffer.BufferAddress();
|
buffer.address = regs.const_buffer.BufferAddress();
|
||||||
buffer.size = regs.const_buffer.cb_size;
|
buffer.size = regs.const_buffer.cb_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
|
#include "video_core/engines/const_buffer_info.h"
|
||||||
#include "video_core/engines/engine_upload.h"
|
#include "video_core/engines/engine_upload.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/macro_interpreter.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");
|
static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
struct ConstBufferInfo {
|
|
||||||
GPUVAddr address;
|
|
||||||
u32 index;
|
|
||||||
u32 size;
|
|
||||||
bool enabled;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ShaderStageInfo {
|
struct ShaderStageInfo {
|
||||||
std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers;
|
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);
|
const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage);
|
||||||
SetupConstBuffers(stage_enum, shader, program_handle, base_bindings);
|
SetupDrawConstBuffers(stage_enum, shader);
|
||||||
SetupGlobalRegions(stage_enum, shader, program_handle, base_bindings);
|
SetupGlobalRegions(stage_enum, shader);
|
||||||
SetupTextures(stage_enum, shader, program_handle, base_bindings);
|
SetupTextures(stage_enum, shader, base_bindings);
|
||||||
|
|
||||||
// Workaround for Intel drivers.
|
// Workaround for Intel drivers.
|
||||||
// When a clip distance is enabled but not set in the shader it crops parts of the screen
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void RasterizerOpenGL::SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
||||||
const Shader& shader, GLuint program_handle,
|
const Shader& shader) {
|
||||||
BaseBindings base_bindings) {
|
|
||||||
MICROPROFILE_SCOPE(OpenGL_UBO);
|
MICROPROFILE_SCOPE(OpenGL_UBO);
|
||||||
const auto& gpu = system.GPU();
|
const auto stage_index = static_cast<std::size_t>(stage);
|
||||||
const auto& maxwell3d = gpu.Maxwell3D();
|
const auto& shader_stage = system.GPU().Maxwell3D().state.shader_stages[stage_index];
|
||||||
const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
|
|
||||||
const auto& entries = shader->GetShaderEntries().const_buffers;
|
const auto& entries = shader->GetShaderEntries().const_buffers;
|
||||||
|
|
||||||
// Upload only the enabled buffers from the 16 constbuffers of each shader stage
|
// Upload only the enabled buffers from the 16 constbuffers of each shader stage
|
||||||
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
|
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
|
||||||
const auto& used_buffer = entries[bindpoint];
|
const auto& entry = entries[bindpoint];
|
||||||
const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
|
SetupConstBuffer(shader_stage.const_buffers[entry.GetIndex()], entry);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
||||||
const Shader& shader, GLenum primitive_mode,
|
const Shader& shader) {
|
||||||
BaseBindings base_bindings) {
|
|
||||||
const auto& entries = shader->GetShaderEntries().global_memory_entries;
|
const auto& entries = shader->GetShaderEntries().global_memory_entries;
|
||||||
for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
|
for (std::size_t bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
|
||||||
const auto& entry{entries[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,
|
void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader,
|
||||||
GLuint program_handle, BaseBindings base_bindings) {
|
BaseBindings base_bindings) {
|
||||||
MICROPROFILE_SCOPE(OpenGL_Texture);
|
MICROPROFILE_SCOPE(OpenGL_Texture);
|
||||||
const auto& gpu = system.GPU();
|
const auto& gpu = system.GPU();
|
||||||
const auto& maxwell3d = gpu.Maxwell3D();
|
const auto& maxwell3d = gpu.Maxwell3D();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "video_core/engines/const_buffer_info.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/rasterizer_cache.h"
|
#include "video_core/rasterizer_cache.h"
|
||||||
#include "video_core/rasterizer_interface.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_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_sampler_cache.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_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_shader_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_state.h"
|
#include "video_core/renderer_opengl/gl_state.h"
|
||||||
#include "video_core/renderer_opengl/utils.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 = {});
|
bool preserve_contents = true, std::optional<std::size_t> single_color_target = {});
|
||||||
|
|
||||||
/// Configures the current constbuffers to use for the draw command.
|
/// Configures the current constbuffers to use for the draw command.
|
||||||
void SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
|
void SetupDrawConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
||||||
GLuint program_handle, BaseBindings base_bindings);
|
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.
|
/// Configures the current global memory entries to use for the draw command.
|
||||||
void SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
void SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
|
||||||
const Shader& shader, GLenum primitive_mode,
|
const Shader& shader);
|
||||||
BaseBindings base_bindings);
|
|
||||||
|
|
||||||
/// Configures the current textures to use for the draw command.
|
/// Configures the current textures to use for the draw command.
|
||||||
void SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
|
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
|
/// Syncs the viewport and depth range to match the guest state
|
||||||
void SyncViewport(OpenGLState& current_state);
|
void SyncViewport(OpenGLState& current_state);
|
||||||
|
|
Loading…
Reference in a new issue