diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 21 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 53 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 6 |
8 files changed, 104 insertions, 16 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 2d7c3152f..98ed11ec5 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -301,5 +301,26 @@ u32 Maxwell3D::GetRegisterValue(u32 method) const { | |||
| 301 | return regs.reg_array[method]; | 301 | return regs.reg_array[method]; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const { | ||
| 305 | // The Vertex stage is always enabled. | ||
| 306 | if (stage == Regs::ShaderStage::Vertex) | ||
| 307 | return true; | ||
| 308 | |||
| 309 | switch (stage) { | ||
| 310 | case Regs::ShaderStage::TesselationControl: | ||
| 311 | return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::TesselationControl)] | ||
| 312 | .enable != 0; | ||
| 313 | case Regs::ShaderStage::TesselationEval: | ||
| 314 | return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::TesselationEval)] | ||
| 315 | .enable != 0; | ||
| 316 | case Regs::ShaderStage::Geometry: | ||
| 317 | return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::Geometry)].enable != 0; | ||
| 318 | case Regs::ShaderStage::Fragment: | ||
| 319 | return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::Fragment)].enable != 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | UNREACHABLE(); | ||
| 323 | } | ||
| 324 | |||
| 304 | } // namespace Engines | 325 | } // namespace Engines |
| 305 | } // namespace Tegra | 326 | } // namespace Tegra |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 9c6236c39..1fae41cb2 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -518,6 +518,9 @@ public: | |||
| 518 | /// Returns a list of enabled textures for the specified shader stage. | 518 | /// Returns a list of enabled textures for the specified shader stage. |
| 519 | std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; | 519 | std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; |
| 520 | 520 | ||
| 521 | /// Returns whether the specified shader stage is enabled or not. | ||
| 522 | bool IsShaderStageEnabled(Regs::ShaderStage stage) const; | ||
| 523 | |||
| 521 | private: | 524 | private: |
| 522 | std::unordered_map<u32, std::vector<u32>> uploaded_macros; | 525 | std::unordered_map<u32, std::vector<u32>> uploaded_macros; |
| 523 | 526 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index f75d4c658..2a2268c20 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -46,6 +46,14 @@ RasterizerOpenGL::RasterizerOpenGL() { | |||
| 46 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; | 46 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | // Create SSBOs | ||
| 50 | for (size_t stage = 0; stage < ssbos.size(); ++stage) { | ||
| 51 | for (size_t buffer = 0; buffer < ssbos[stage].size(); ++buffer) { | ||
| 52 | ssbos[stage][buffer].Create(); | ||
| 53 | state.draw.const_buffers[stage][buffer].ssbo = ssbos[stage][buffer].handle; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 49 | GLint ext_num; | 57 | GLint ext_num; |
| 50 | glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); | 58 | glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); |
| 51 | for (GLint i = 0; i < ext_num; i++) { | 59 | for (GLint i = 0; i < ext_num; i++) { |
| @@ -191,8 +199,9 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size | |||
| 191 | auto& shader_config = gpu.regs.shader_config[index]; | 199 | auto& shader_config = gpu.regs.shader_config[index]; |
| 192 | const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; | 200 | const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; |
| 193 | 201 | ||
| 194 | // VertexB program is always enabled, despite bit setting | 202 | const auto& stage = index - 1; // Stage indices are 0 - 5 |
| 195 | const bool is_enabled{shader_config.enable || program == Maxwell::ShaderProgram::VertexB}; | 203 | |
| 204 | const bool is_enabled = gpu.IsShaderStageEnabled(static_cast<Maxwell::ShaderStage>(stage)); | ||
| 196 | 205 | ||
| 197 | // Skip stages that are not enabled | 206 | // Skip stages that are not enabled |
| 198 | if (!is_enabled) { | 207 | if (!is_enabled) { |
| @@ -200,7 +209,6 @@ void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size | |||
| 200 | } | 209 | } |
| 201 | 210 | ||
| 202 | // Upload uniform data as one UBO per stage | 211 | // Upload uniform data as one UBO per stage |
| 203 | const auto& stage = index - 1; // Stage indices are 0 - 5 | ||
| 204 | const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); | 212 | const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); |
| 205 | copy_buffer(uniform_buffers[stage].handle, ubo_offset, | 213 | copy_buffer(uniform_buffers[stage].handle, ubo_offset, |
| 206 | sizeof(GLShader::MaxwellUniformData)); | 214 | sizeof(GLShader::MaxwellUniformData)); |
| @@ -298,6 +306,8 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 298 | 306 | ||
| 299 | // Sync and bind the texture surfaces | 307 | // Sync and bind the texture surfaces |
| 300 | BindTextures(); | 308 | BindTextures(); |
| 309 | // Configure the constant buffer objects | ||
| 310 | SetupConstBuffers(); | ||
| 301 | 311 | ||
| 302 | // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable | 312 | // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable |
| 303 | // scissor test to prevent drawing outside of the framebuffer region | 313 | // scissor test to prevent drawing outside of the framebuffer region |
| @@ -380,7 +390,7 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 380 | 390 | ||
| 381 | void RasterizerOpenGL::BindTextures() { | 391 | void RasterizerOpenGL::BindTextures() { |
| 382 | using Regs = Tegra::Engines::Maxwell3D::Regs; | 392 | using Regs = Tegra::Engines::Maxwell3D::Regs; |
| 383 | auto maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); | 393 | auto& maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); |
| 384 | 394 | ||
| 385 | // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a | 395 | // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a |
| 386 | // certain number in OpenGL. We try to only use the minimum amount of host textures by not | 396 | // certain number in OpenGL. We try to only use the minimum amount of host textures by not |
| @@ -527,6 +537,41 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr | |||
| 527 | } | 537 | } |
| 528 | } | 538 | } |
| 529 | 539 | ||
| 540 | void RasterizerOpenGL::SetupConstBuffers() { | ||
| 541 | using Regs = Tegra::Engines::Maxwell3D::Regs; | ||
| 542 | auto& gpu = Core::System::GetInstance().GPU(); | ||
| 543 | auto& maxwell3d = gpu.Get3DEngine(); | ||
| 544 | |||
| 545 | // Upload only the enabled buffers from the 16 constbuffers of each shader stage | ||
| 546 | u32 current_bindpoint = 0; | ||
| 547 | for (u32 stage = 0; stage < Regs::MaxShaderStage; ++stage) { | ||
| 548 | auto& shader_stage = maxwell3d.state.shader_stages[stage]; | ||
| 549 | bool stage_enabled = maxwell3d.IsShaderStageEnabled(static_cast<Regs::ShaderStage>(stage)); | ||
| 550 | |||
| 551 | for (u32 buffer_id = 0; buffer_id < Regs::MaxConstBuffers; ++buffer_id) { | ||
| 552 | const auto& buffer = shader_stage.const_buffers[buffer_id]; | ||
| 553 | |||
| 554 | state.draw.const_buffers[stage][buffer_id].enabled = buffer.enabled && stage_enabled; | ||
| 555 | |||
| 556 | if (buffer.enabled && stage_enabled) { | ||
| 557 | state.draw.const_buffers[stage][buffer_id].bindpoint = current_bindpoint; | ||
| 558 | current_bindpoint++; | ||
| 559 | |||
| 560 | VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address); | ||
| 561 | const u8* data = Memory::GetPointer(addr); | ||
| 562 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, | ||
| 563 | state.draw.const_buffers[stage][buffer_id].ssbo); | ||
| 564 | glBufferData(GL_SHADER_STORAGE_BUFFER, buffer.size, data, GL_DYNAMIC_DRAW); | ||
| 565 | glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); | ||
| 566 | } else { | ||
| 567 | state.draw.const_buffers[stage][buffer_id].bindpoint = -1; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | |||
| 572 | state.Apply(); | ||
| 573 | } | ||
| 574 | |||
| 530 | void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, | 575 | void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, |
| 531 | const Surface& depth_surface, bool has_stencil) { | 576 | const Surface& depth_surface, bool has_stencil) { |
| 532 | state.draw.draw_framebuffer = framebuffer.handle; | 577 | state.draw.draw_framebuffer = framebuffer.handle; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 71c21c69b..bf3308aef 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -87,6 +87,9 @@ private: | |||
| 87 | /// Binds the required textures to OpenGL before drawing a batch. | 87 | /// Binds the required textures to OpenGL before drawing a batch. |
| 88 | void BindTextures(); | 88 | void BindTextures(); |
| 89 | 89 | ||
| 90 | /// Configures the current constbuffers to use for the draw command. | ||
| 91 | void SetupConstBuffers(); | ||
| 92 | |||
| 90 | /// Syncs the viewport to match the guest state | 93 | /// Syncs the viewport to match the guest state |
| 91 | void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); | 94 | void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); |
| 92 | 95 | ||
| @@ -129,6 +132,10 @@ private: | |||
| 129 | std::array<bool, 16> hw_vao_enabled_attributes; | 132 | std::array<bool, 16> hw_vao_enabled_attributes; |
| 130 | 133 | ||
| 131 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; | 134 | std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers; |
| 135 | std::array<std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers>, | ||
| 136 | Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> | ||
| 137 | ssbos; | ||
| 138 | |||
| 132 | static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024; | 139 | static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024; |
| 133 | std::unique_ptr<OGLStreamBuffer> vertex_buffer; | 140 | std::unique_ptr<OGLStreamBuffer> vertex_buffer; |
| 134 | OGLBuffer uniform_buffer; | 141 | OGLBuffer uniform_buffer; |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 7fceedce8..85b838faa 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -53,13 +53,6 @@ void SetShaderSamplerBindings(GLuint shader) { | |||
| 53 | 53 | ||
| 54 | } // namespace Impl | 54 | } // namespace Impl |
| 55 | 55 | ||
| 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { | 56 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {} |
| 57 | const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager; | ||
| 58 | for (unsigned index = 0; index < shader_stage.const_buffers.size(); ++index) { | ||
| 59 | const auto& const_buffer = shader_stage.const_buffers[index]; | ||
| 60 | const VAddr vaddr = memory_manager->PhysicalToVirtualAddress(const_buffer.address); | ||
| 61 | Memory::ReadBlock(vaddr, const_buffers[index].data(), sizeof(ConstBuffer)); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | 57 | ||
| 65 | } // namespace GLShader | 58 | } // namespace GLShader |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 5c8560cf5..f003ce532 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -30,11 +30,10 @@ void SetShaderSamplerBindings(GLuint shader); | |||
| 30 | // Not following that rule will cause problems on some AMD drivers. | 30 | // Not following that rule will cause problems on some AMD drivers. |
| 31 | struct MaxwellUniformData { | 31 | struct MaxwellUniformData { |
| 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); |
| 33 | 33 | // TODO(Subv): Use this for something. | |
| 34 | using ConstBuffer = std::array<GLvec4, 4>; | ||
| 35 | alignas(16) std::array<ConstBuffer, Maxwell3D::Regs::MaxConstBuffers> const_buffers; | ||
| 36 | }; | 34 | }; |
| 37 | static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is incorrect"); | 35 | // static_assert(sizeof(MaxwellUniformData) == 1024, "MaxwellUniformData structure size is |
| 36 | // incorrect"); | ||
| 38 | static_assert(sizeof(MaxwellUniformData) < 16384, | 37 | static_assert(sizeof(MaxwellUniformData) < 16384, |
| 39 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | 38 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); |
| 40 | 39 | ||
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 6da3a7781..7b8a15ed2 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -202,6 +202,20 @@ void OpenGLState::Apply() const { | |||
| 202 | } | 202 | } |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | // Constbuffers | ||
| 206 | for (u32 stage = 0; stage < draw.const_buffers.size(); ++stage) { | ||
| 207 | for (u32 buffer_id = 0; buffer_id < draw.const_buffers[stage].size(); ++buffer_id) { | ||
| 208 | auto& current = cur_state.draw.const_buffers[stage][buffer_id]; | ||
| 209 | auto& new_state = draw.const_buffers[stage][buffer_id]; | ||
| 210 | if (current.enabled != new_state.enabled || current.bindpoint != new_state.bindpoint || | ||
| 211 | current.ssbo != new_state.ssbo) { | ||
| 212 | if (new_state.enabled) { | ||
| 213 | glBindBufferBase(GL_SHADER_STORAGE_BUFFER, new_state.bindpoint, new_state.ssbo); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 205 | // Lighting LUTs | 219 | // Lighting LUTs |
| 206 | if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) { | 220 | if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) { |
| 207 | glActiveTexture(TextureUnits::LightingLUT.Enum()); | 221 | glActiveTexture(TextureUnits::LightingLUT.Enum()); |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index b18af14bb..6a80e6a7d 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -123,6 +123,12 @@ public: | |||
| 123 | GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING | 123 | GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING |
| 124 | GLuint shader_program; // GL_CURRENT_PROGRAM | 124 | GLuint shader_program; // GL_CURRENT_PROGRAM |
| 125 | GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING | 125 | GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING |
| 126 | struct ConstBufferConfig { | ||
| 127 | bool enabled; | ||
| 128 | GLuint bindpoint; | ||
| 129 | GLuint ssbo; | ||
| 130 | }; | ||
| 131 | std::array<std::array<ConstBufferConfig, 16>, 5> const_buffers{}; | ||
| 126 | } draw; | 132 | } draw; |
| 127 | 133 | ||
| 128 | struct { | 134 | struct { |