diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 83 |
1 files changed, 46 insertions, 37 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 0a33868b7..e9eb03ad9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -196,8 +196,10 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) { auto& gpu = Core::System().GetInstance().GPU().Maxwell3D(); ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!"); - // Next available bindpoint to use when uploading the const buffers to the GLSL shaders. + // Next available bindpoints to use when uploading the const buffers and textures to the GLSL + // shaders. u32 current_constbuffer_bindpoint = 0; + u32 current_texture_bindpoint = 0; for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { auto& shader_config = gpu.regs.shader_config[index]; @@ -258,6 +260,11 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset) { current_constbuffer_bindpoint = SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), gl_stage_program, current_constbuffer_bindpoint, shader_resources.const_buffer_entries); + + // Configure the textures for this shader stage. + current_texture_bindpoint = + SetupTextures(static_cast<Maxwell::ShaderStage>(stage), gl_stage_program, + current_texture_bindpoint, shader_resources.texture_samplers); } shader_program_manager->UseTrivialGeometryShader(); @@ -341,9 +348,6 @@ void RasterizerOpenGL::DrawArrays() { // TODO(bunnei): Sync framebuffer_scale uniform here // TODO(bunnei): Sync scissorbox uniform(s) here - // Sync and bind the texture surfaces - BindTextures(); - // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable // scissor test to prevent drawing outside of the framebuffer region state.scissor.enabled = true; @@ -447,39 +451,6 @@ void RasterizerOpenGL::DrawArrays() { } } -void RasterizerOpenGL::BindTextures() { - using Regs = Tegra::Engines::Maxwell3D::Regs; - auto& maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); - - // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a - // certain number in OpenGL. We try to only use the minimum amount of host textures by not - // keeping a 1:1 relation between guest texture ids and host texture ids, ie, guest texture id 8 - // can be host texture id 0 if it's the only texture used in the guest shader program. - u32 host_texture_index = 0; - for (u32 stage = 0; stage < Regs::MaxShaderStage; ++stage) { - ASSERT(host_texture_index < texture_samplers.size()); - const auto textures = maxwell3d.GetStageTextures(static_cast<Regs::ShaderStage>(stage)); - for (unsigned texture_index = 0; texture_index < textures.size(); ++texture_index) { - const auto& texture = textures[texture_index]; - - if (texture.enabled) { - texture_samplers[host_texture_index].SyncWithConfig(texture.tsc); - Surface surface = res_cache.GetTextureSurface(texture); - if (surface != nullptr) { - state.texture_units[host_texture_index].texture_2d = surface->texture.handle; - } else { - // Can occur when texture addr is null or its memory is unmapped/invalid - state.texture_units[texture_index].texture_2d = 0; - } - - ++host_texture_index; - } else { - state.texture_units[texture_index].texture_2d = 0; - } - } - } -} - void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) { const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; switch (method) { @@ -674,6 +645,44 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint progr return current_bindpoint + entries.size(); } +u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, GLuint program, u32 current_unit, + const std::vector<GLShader::SamplerEntry>& entries) { + auto& gpu = Core::System::GetInstance().GPU(); + auto& maxwell3d = gpu.Get3DEngine(); + + ASSERT_MSG(maxwell3d.IsShaderStageEnabled(stage), + "Attempted to upload textures of disabled shader stage"); + + ASSERT_MSG(current_unit + 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]; + u32 current_bindpoint = current_unit + bindpoint; + + // Bind the uniform to the sampler. + GLint uniform = glGetUniformLocation(program, entry.GetName().c_str()); + ASSERT(uniform != -1); + glProgramUniform1i(program, uniform, current_bindpoint); + + const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset()); + ASSERT(texture.enabled); + + texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); + Surface surface = res_cache.GetTextureSurface(texture); + if (surface != nullptr) { + state.texture_units[current_bindpoint].texture_2d = surface->texture.handle; + } else { + // Can occur when texture addr is null or its memory is unmapped/invalid + state.texture_units[current_bindpoint].texture_2d = 0; + } + } + + state.Apply(); + + return current_unit + entries.size(); +} + void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, bool has_stencil) { state.draw.draw_framebuffer = framebuffer.handle; |