diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 102 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 7 |
2 files changed, 77 insertions, 32 deletions
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2d58df45b..f75d4c658 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -96,10 +96,14 @@ RasterizerOpenGL::RasterizerOpenGL() { | |||
| 96 | 96 | ||
| 97 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle()); | 97 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle()); |
| 98 | 98 | ||
| 99 | vs_uniform_buffer.Create(); | 99 | for (unsigned index = 0; index < uniform_buffers.size(); ++index) { |
| 100 | glBindBuffer(GL_UNIFORM_BUFFER, vs_uniform_buffer.handle); | 100 | auto& buffer = uniform_buffers[index]; |
| 101 | glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::VSUniformData), nullptr, GL_STREAM_COPY); | 101 | buffer.Create(); |
| 102 | glBindBufferBase(GL_UNIFORM_BUFFER, 1, vs_uniform_buffer.handle); | 102 | glBindBuffer(GL_UNIFORM_BUFFER, buffer.handle); |
| 103 | glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::MaxwellUniformData), nullptr, | ||
| 104 | GL_STREAM_COPY); | ||
| 105 | glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle); | ||
| 106 | } | ||
| 103 | 107 | ||
| 104 | accelerate_draw = AccelDraw::Disabled; | 108 | accelerate_draw = AccelDraw::Disabled; |
| 105 | 109 | ||
| @@ -167,15 +171,69 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { | |||
| 167 | buffer_offset += data_size; | 171 | buffer_offset += data_size; |
| 168 | } | 172 | } |
| 169 | 173 | ||
| 170 | void RasterizerOpenGL::SetupVertexShader(GLShader::VSUniformData* ub_ptr, GLintptr buffer_offset) { | 174 | void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos) { |
| 171 | MICROPROFILE_SCOPE(OpenGL_VS); | 175 | // Helper function for uploading uniform data |
| 172 | UNREACHABLE(); | 176 | const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { |
| 173 | } | 177 | if (has_ARB_direct_state_access) { |
| 178 | glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size); | ||
| 179 | } else { | ||
| 180 | glBindBuffer(GL_COPY_WRITE_BUFFER, handle); | ||
| 181 | glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size); | ||
| 182 | } | ||
| 183 | }; | ||
| 174 | 184 | ||
| 175 | void RasterizerOpenGL::SetupFragmentShader(GLShader::FSUniformData* ub_ptr, | 185 | auto& gpu = Core::System().GetInstance().GPU().Maxwell3D(); |
| 176 | GLintptr buffer_offset) { | 186 | ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!"); |
| 177 | MICROPROFILE_SCOPE(OpenGL_FS); | 187 | |
| 178 | UNREACHABLE(); | 188 | for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) { |
| 189 | ptr_pos += sizeof(GLShader::MaxwellUniformData); | ||
| 190 | |||
| 191 | auto& shader_config = gpu.regs.shader_config[index]; | ||
| 192 | const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)}; | ||
| 193 | |||
| 194 | // VertexB program is always enabled, despite bit setting | ||
| 195 | const bool is_enabled{shader_config.enable || program == Maxwell::ShaderProgram::VertexB}; | ||
| 196 | |||
| 197 | // Skip stages that are not enabled | ||
| 198 | if (!is_enabled) { | ||
| 199 | continue; | ||
| 200 | } | ||
| 201 | |||
| 202 | // 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); | ||
| 205 | copy_buffer(uniform_buffers[stage].handle, ubo_offset, | ||
| 206 | sizeof(GLShader::MaxwellUniformData)); | ||
| 207 | GLShader::MaxwellUniformData* ub_ptr = | ||
| 208 | reinterpret_cast<GLShader::MaxwellUniformData*>(&buffer_ptr[ptr_pos]); | ||
| 209 | ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]); | ||
| 210 | |||
| 211 | // Fetch program code from memory | ||
| 212 | GLShader::ProgramCode program_code; | ||
| 213 | const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset}; | ||
| 214 | const VAddr cpu_address{gpu.memory_manager.PhysicalToVirtualAddress(gpu_address)}; | ||
| 215 | Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64)); | ||
| 216 | GLShader::ShaderSetup setup{std::move(program_code)}; | ||
| 217 | |||
| 218 | switch (program) { | ||
| 219 | case Maxwell::ShaderProgram::VertexB: { | ||
| 220 | GLShader::MaxwellVSConfig vs_config{setup}; | ||
| 221 | shader_program_manager->UseProgrammableVertexShader(vs_config, setup); | ||
| 222 | break; | ||
| 223 | } | ||
| 224 | case Maxwell::ShaderProgram::Fragment: { | ||
| 225 | GLShader::MaxwellFSConfig fs_config{setup}; | ||
| 226 | shader_program_manager->UseProgrammableFragmentShader(fs_config, setup); | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | default: | ||
| 230 | LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index, | ||
| 231 | shader_config.enable.Value(), shader_config.offset); | ||
| 232 | UNREACHABLE(); | ||
| 233 | } | ||
| 234 | } | ||
| 235 | |||
| 236 | shader_program_manager->UseTrivialGeometryShader(); | ||
| 179 | } | 237 | } |
| 180 | 238 | ||
| 181 | bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { | 239 | bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { |
| @@ -260,7 +318,9 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 260 | if (is_indexed) { | 318 | if (is_indexed) { |
| 261 | UNREACHABLE(); | 319 | UNREACHABLE(); |
| 262 | } | 320 | } |
| 263 | buffer_size += sizeof(GLShader::VSUniformData); | 321 | |
| 322 | // Uniform space for the 5 shader stages | ||
| 323 | buffer_size += sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage; | ||
| 264 | 324 | ||
| 265 | size_t ptr_pos = 0; | 325 | size_t ptr_pos = 0; |
| 266 | u8* buffer_ptr; | 326 | u8* buffer_ptr; |
| @@ -276,24 +336,10 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 276 | UNREACHABLE(); | 336 | UNREACHABLE(); |
| 277 | } | 337 | } |
| 278 | 338 | ||
| 279 | SetupVertexShader(reinterpret_cast<GLShader::VSUniformData*>(&buffer_ptr[ptr_pos]), | 339 | SetupShaders(buffer_ptr, buffer_offset, ptr_pos); |
| 280 | buffer_offset + static_cast<GLintptr>(ptr_pos)); | ||
| 281 | const GLintptr vs_ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); | ||
| 282 | ptr_pos += sizeof(GLShader::VSUniformData); | ||
| 283 | 340 | ||
| 284 | stream_buffer->Unmap(); | 341 | stream_buffer->Unmap(); |
| 285 | 342 | ||
| 286 | const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { | ||
| 287 | if (has_ARB_direct_state_access) { | ||
| 288 | glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size); | ||
| 289 | } else { | ||
| 290 | glBindBuffer(GL_COPY_WRITE_BUFFER, handle); | ||
| 291 | glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size); | ||
| 292 | } | ||
| 293 | }; | ||
| 294 | |||
| 295 | copy_buffer(vs_uniform_buffer.handle, vs_ubo_offset, sizeof(GLShader::VSUniformData)); | ||
| 296 | |||
| 297 | shader_program_manager->ApplyTo(state); | 343 | shader_program_manager->ApplyTo(state); |
| 298 | state.Apply(); | 344 | state.Apply(); |
| 299 | 345 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index b508f5acc..32b897eb2 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "common/hash.h" | 16 | #include "common/hash.h" |
| 17 | #include "common/vector_math.h" | 17 | #include "common/vector_math.h" |
| 18 | #include "video_core/engines/maxwell_3d.h" | ||
| 18 | #include "video_core/rasterizer_interface.h" | 19 | #include "video_core/rasterizer_interface.h" |
| 19 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" | 20 | #include "video_core/renderer_opengl/gl_rasterizer_cache.h" |
| 20 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 21 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| @@ -141,11 +142,9 @@ private: | |||
| 141 | void AnalyzeVertexArray(bool is_indexed); | 142 | void AnalyzeVertexArray(bool is_indexed); |
| 142 | void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); | 143 | void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); |
| 143 | 144 | ||
| 144 | OGLBuffer vs_uniform_buffer; | 145 | std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers; |
| 145 | 146 | ||
| 146 | void SetupVertexShader(GLShader::VSUniformData* ub_ptr, GLintptr buffer_offset); | 147 | void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos); |
| 147 | |||
| 148 | void SetupFragmentShader(GLShader::FSUniformData* ub_ptr, GLintptr buffer_offset); | ||
| 149 | 148 | ||
| 150 | enum class AccelDraw { Disabled, Arrays, Indexed }; | 149 | enum class AccelDraw { Disabled, Arrays, Indexed }; |
| 151 | AccelDraw accelerate_draw; | 150 | AccelDraw accelerate_draw; |