summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_opengl/gl_rasterizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_opengl/gl_rasterizer.cpp')
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp151
1 files changed, 69 insertions, 82 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 6600ad528..9f7c837d6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -297,10 +297,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
MICROPROFILE_SCOPE(OpenGL_Shader);
auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
- // Next available bindpoints to use when uploading the const buffers and textures to the GLSL
- // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
- u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
- u32 current_texture_bindpoint = 0;
+ BaseBindings base_bindings;
std::array<bool, Maxwell::NumClipDistances> clip_distances{};
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
@@ -324,43 +321,35 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
const GLintptr offset = buffer_cache.UploadHostMemory(
&ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
- // Bind the buffer
- glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(stage), buffer_cache.GetHandle(),
- offset, static_cast<GLsizeiptr>(sizeof(ubo)));
+ // Bind the emulation info buffer
+ glBindBufferRange(GL_UNIFORM_BUFFER, base_bindings.cbuf, buffer_cache.GetHandle(), offset,
+ static_cast<GLsizeiptr>(sizeof(ubo)));
Shader shader{shader_cache.GetStageProgram(program)};
+ const auto [program_handle, next_bindings] =
+ shader->GetProgramHandle(primitive_mode, base_bindings);
switch (program) {
case Maxwell::ShaderProgram::VertexA:
- case Maxwell::ShaderProgram::VertexB: {
- shader_program_manager->UseProgrammableVertexShader(
- shader->GetProgramHandle(primitive_mode));
+ case Maxwell::ShaderProgram::VertexB:
+ shader_program_manager->UseProgrammableVertexShader(program_handle);
break;
- }
- case Maxwell::ShaderProgram::Geometry: {
- shader_program_manager->UseProgrammableGeometryShader(
- shader->GetProgramHandle(primitive_mode));
+ case Maxwell::ShaderProgram::Geometry:
+ shader_program_manager->UseProgrammableGeometryShader(program_handle);
break;
- }
- case Maxwell::ShaderProgram::Fragment: {
- shader_program_manager->UseProgrammableFragmentShader(
- shader->GetProgramHandle(primitive_mode));
+ case Maxwell::ShaderProgram::Fragment:
+ shader_program_manager->UseProgrammableFragmentShader(program_handle);
break;
- }
default:
LOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset=0x{:08X}", index,
shader_config.enable.Value(), shader_config.offset);
UNREACHABLE();
}
- // Configure the const buffers for this shader stage.
- current_constbuffer_bindpoint =
- SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), shader, primitive_mode,
- current_constbuffer_bindpoint);
-
- // Configure the textures for this shader stage.
- current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
- primitive_mode, current_texture_bindpoint);
+ 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);
// Workaround for Intel drivers.
// When a clip distance is enabled but not set in the shader it crops parts of the screen
@@ -375,6 +364,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
// VertexB was combined with VertexA, so we skip the VertexB iteration
index++;
}
+
+ base_bindings = next_bindings;
}
SyncClipEnabled(clip_distances);
@@ -486,9 +477,9 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
cached_pages.add({pages_interval, delta});
}
-void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool using_color_fb,
- bool using_depth_fb, bool preserve_contents,
- std::optional<std::size_t> single_color_target) {
+std::pair<bool, bool> RasterizerOpenGL::ConfigureFramebuffers(
+ OpenGLState& current_state, bool using_color_fb, bool using_depth_fb, bool preserve_contents,
+ std::optional<std::size_t> single_color_target) {
MICROPROFILE_SCOPE(OpenGL_Framebuffer);
const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
const auto& regs = gpu.regs;
@@ -500,7 +491,7 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
// Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or
// single color targets). This is done because the guest registers may not change but the
// host framebuffer may contain different attachments
- return;
+ return current_depth_stencil_usage;
}
current_framebuffer_config_state = fb_config_state;
@@ -570,12 +561,14 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us
depth_surface->MarkAsModified(true, res_cache);
fbkey.zeta = depth_surface->Texture().handle;
- fbkey.stencil_enable = regs.stencil_enable;
+ fbkey.stencil_enable = regs.stencil_enable &&
+ depth_surface->GetSurfaceParams().type == SurfaceType::DepthStencil;
}
SetupCachedFramebuffer(fbkey, current_state);
-
SyncViewport(current_state);
+
+ return current_depth_stencil_usage = {static_cast<bool>(depth_surface), fbkey.stencil_enable};
}
void RasterizerOpenGL::Clear() {
@@ -643,8 +636,8 @@ void RasterizerOpenGL::Clear() {
return;
}
- ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false,
- regs.clear_buffers.RT.Value());
+ const auto [clear_depth, clear_stencil] = ConfigureFramebuffers(
+ clear_state, use_color, use_depth || use_stencil, false, regs.clear_buffers.RT.Value());
if (regs.clear_flags.scissor) {
SyncScissorTest(clear_state);
}
@@ -659,11 +652,11 @@ void RasterizerOpenGL::Clear() {
glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
}
- if (use_depth && use_stencil) {
+ if (clear_depth && clear_stencil) {
glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
- } else if (use_depth) {
+ } else if (clear_depth) {
glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
- } else if (use_stencil) {
+ } else if (clear_stencil) {
glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
}
}
@@ -790,11 +783,6 @@ bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs
return true;
}
-bool RasterizerOpenGL::AccelerateFill(const void* config) {
- UNREACHABLE();
- return true;
-}
-
bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
VAddr framebuffer_addr, u32 pixel_stride) {
if (!framebuffer_addr) {
@@ -924,13 +912,14 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
}
}
-u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader,
- GLenum primitive_mode, u32 current_bindpoint) {
+void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
+ const Shader& shader, GLuint program_handle,
+ BaseBindings base_bindings) {
MICROPROFILE_SCOPE(OpenGL_UBO);
const auto& gpu = Core::System::GetInstance().GPU();
const auto& maxwell3d = gpu.Maxwell3D();
const auto& shader_stage = maxwell3d.state.shader_stages[static_cast<std::size_t>(stage)];
- const auto& entries = shader->GetShaderEntries().const_buffer_entries;
+ const auto& entries = shader->GetShaderEntries().const_buffers;
constexpr u64 max_binds = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers;
std::array<GLuint, max_binds> bind_buffers;
@@ -965,7 +954,7 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
}
} else {
// Buffer is accessed directly, upload just what we use
- size = used_buffer.GetSize() * sizeof(float);
+ size = used_buffer.GetSize();
}
// Align the actual size so it ends up being a multiple of vec4 to meet the OpenGL std140
@@ -973,75 +962,73 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
size = Common::AlignUp(size, sizeof(GLvec4));
ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
- GLintptr const_buffer_offset = buffer_cache.UploadMemory(
+ const GLintptr const_buffer_offset = buffer_cache.UploadMemory(
buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment));
- // Now configure the bindpoint of the buffer inside the shader
- glUniformBlockBinding(shader->GetProgramHandle(primitive_mode),
- shader->GetProgramResourceIndex(used_buffer),
- current_bindpoint + bindpoint);
-
// Prepare values for multibind
bind_buffers[bindpoint] = buffer_cache.GetHandle();
bind_offsets[bindpoint] = const_buffer_offset;
bind_sizes[bindpoint] = size;
}
- glBindBuffersRange(GL_UNIFORM_BUFFER, current_bindpoint, static_cast<GLsizei>(entries.size()),
+ // The first binding is reserved for emulation values
+ const GLuint ubo_base_binding = base_bindings.cbuf + 1;
+ glBindBuffersRange(GL_UNIFORM_BUFFER, ubo_base_binding, static_cast<GLsizei>(entries.size()),
bind_buffers.data(), bind_offsets.data(), bind_sizes.data());
+}
+
+void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
+ const Shader& shader, GLenum primitive_mode,
+ BaseBindings base_bindings) {
+ // TODO(Rodrigo): Use ARB_multi_bind here
+ const auto& entries = shader->GetShaderEntries().global_memory_entries;
- return current_bindpoint + static_cast<u32>(entries.size());
+ for (u32 bindpoint = 0; bindpoint < static_cast<u32>(entries.size()); ++bindpoint) {
+ const auto& entry = entries[bindpoint];
+ const u32 current_bindpoint = base_bindings.gmem + bindpoint;
+ const auto& region = global_cache.GetGlobalRegion(entry, stage);
+
+ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle());
+ }
}
-u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
- GLenum primitive_mode, u32 current_unit) {
+void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader,
+ GLuint program_handle, BaseBindings base_bindings) {
MICROPROFILE_SCOPE(OpenGL_Texture);
const auto& gpu = Core::System::GetInstance().GPU();
const auto& maxwell3d = gpu.Maxwell3D();
- const auto& entries = shader->GetShaderEntries().texture_samplers;
+ const auto& entries = shader->GetShaderEntries().samplers;
- ASSERT_MSG(current_unit + entries.size() <= std::size(state.texture_units),
+ ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.texture_units),
"Exceeded the number of active textures.");
for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
const auto& entry = entries[bindpoint];
- const u32 current_bindpoint = current_unit + bindpoint;
-
- // Bind the uniform to the sampler.
-
- glProgramUniform1i(shader->GetProgramHandle(primitive_mode),
- shader->GetUniformLocation(entry), current_bindpoint);
+ const u32 current_bindpoint = base_bindings.sampler + bindpoint;
+ auto& unit = state.texture_units[current_bindpoint];
const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset());
-
if (!texture.enabled) {
- state.texture_units[current_bindpoint].texture = 0;
+ unit.texture = 0;
continue;
}
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
+
Surface surface = res_cache.GetTextureSurface(texture, entry);
if (surface != nullptr) {
- const GLuint handle =
+ unit.texture =
entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
- const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
- state.texture_units[current_bindpoint].texture = handle;
- state.texture_units[current_bindpoint].target = target;
- state.texture_units[current_bindpoint].swizzle.r =
- MaxwellToGL::SwizzleSource(texture.tic.x_source);
- state.texture_units[current_bindpoint].swizzle.g =
- MaxwellToGL::SwizzleSource(texture.tic.y_source);
- state.texture_units[current_bindpoint].swizzle.b =
- MaxwellToGL::SwizzleSource(texture.tic.z_source);
- state.texture_units[current_bindpoint].swizzle.a =
- MaxwellToGL::SwizzleSource(texture.tic.w_source);
+ unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
+ unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source);
+ unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source);
+ unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source);
+ unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source);
} else {
// Can occur when texture addr is null or its memory is unmapped/invalid
- state.texture_units[current_bindpoint].texture = 0;
+ unit.texture = 0;
}
}
-
- return current_unit + static_cast<u32>(entries.size());
}
void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {