|
|
|
@ -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; |
|
|
|
} |
|
|
|
const auto& entry = entries[bindpoint]; |
|
|
|
SetupConstBuffer(shader_stage.const_buffers[entry.GetIndex()], entry); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
std::size_t size = 0; |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
if (used_buffer.IsIndirect()) { |
|
|
|
// Buffer is accessed indirectly, so upload the entire thing
|
|
|
|
size = buffer.size; |
|
|
|
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 = used_buffer.GetSize(); |
|
|
|
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, "Constbuffer too big"); |
|
|
|
|
|
|
|
const GLintptr const_buffer_offset = |
|
|
|
buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); |
|
|
|
// 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"); |
|
|
|
|
|
|
|
bind_ubo_pushbuffer.Push(buffer_cache.GetHandle(), const_buffer_offset, size); |
|
|
|
} |
|
|
|
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(); |
|
|
|
|