diff options
| author | 2020-03-02 19:31:26 -0300 | |
|---|---|---|
| committer | 2020-03-13 18:33:04 -0300 | |
| commit | 8e9f23f393763a6d76605206eeb20f6f8885d9a9 (patch) | |
| tree | 35b28be3f345cd0223732b4803e13de40764d1dc /src | |
| parent | gl_shader_decompiler: Decorate output attributes with XFB layout (diff) | |
| download | yuzu-8e9f23f393763a6d76605206eeb20f6f8885d9a9.tar.gz yuzu-8e9f23f393763a6d76605206eeb20f6f8885d9a9.tar.xz yuzu-8e9f23f393763a6d76605206eeb20f6f8885d9a9.zip | |
gl_rasterizer: Implement transform feedback bindings
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 70 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 14 |
3 files changed, 83 insertions, 10 deletions
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 8752a1cfb..ba9c76593 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -634,6 +634,11 @@ public: | |||
| 634 | u32 address_low; | 634 | u32 address_low; |
| 635 | s32 buffer_size; | 635 | s32 buffer_size; |
| 636 | s32 buffer_offset; | 636 | s32 buffer_offset; |
| 637 | |||
| 638 | GPUVAddr Address() const { | ||
| 639 | return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | | ||
| 640 | address_low); | ||
| 641 | } | ||
| 637 | }; | 642 | }; |
| 638 | static_assert(sizeof(TransformFeedbackBinding) == 32); | 643 | static_assert(sizeof(TransformFeedbackBinding) == 32); |
| 639 | 644 | ||
| @@ -652,6 +657,10 @@ public: | |||
| 652 | return shader_config[index].enable != 0; | 657 | return shader_config[index].enable != 0; |
| 653 | } | 658 | } |
| 654 | 659 | ||
| 660 | bool IsShaderConfigEnabled(Regs::ShaderProgram type) const { | ||
| 661 | return IsShaderConfigEnabled(static_cast<std::size_t>(type)); | ||
| 662 | } | ||
| 663 | |||
| 655 | union { | 664 | union { |
| 656 | struct { | 665 | struct { |
| 657 | INSERT_UNION_PADDING_WORDS(0x45); | 666 | INSERT_UNION_PADDING_WORDS(0x45); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 8a2db8e36..1af4268a4 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -496,7 +496,6 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 496 | SyncCullMode(); | 496 | SyncCullMode(); |
| 497 | SyncPrimitiveRestart(); | 497 | SyncPrimitiveRestart(); |
| 498 | SyncScissorTest(); | 498 | SyncScissorTest(); |
| 499 | SyncTransformFeedback(); | ||
| 500 | SyncPointState(); | 499 | SyncPointState(); |
| 501 | SyncPolygonOffset(); | 500 | SyncPolygonOffset(); |
| 502 | SyncAlphaTest(); | 501 | SyncAlphaTest(); |
| @@ -569,7 +568,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 569 | glTextureBarrier(); | 568 | glTextureBarrier(); |
| 570 | } | 569 | } |
| 571 | 570 | ||
| 572 | ++num_queued_commands; | 571 | BeginTransformFeedback(primitive_mode); |
| 573 | 572 | ||
| 574 | const GLuint base_instance = static_cast<GLuint>(gpu.regs.vb_base_instance); | 573 | const GLuint base_instance = static_cast<GLuint>(gpu.regs.vb_base_instance); |
| 575 | const GLsizei num_instances = | 574 | const GLsizei num_instances = |
| @@ -608,6 +607,10 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 608 | num_instances, base_instance); | 607 | num_instances, base_instance); |
| 609 | } | 608 | } |
| 610 | } | 609 | } |
| 610 | |||
| 611 | EndTransformFeedback(); | ||
| 612 | |||
| 613 | ++num_queued_commands; | ||
| 611 | } | 614 | } |
| 612 | 615 | ||
| 613 | void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { | 616 | void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { |
| @@ -1290,11 +1293,6 @@ void RasterizerOpenGL::SyncScissorTest() { | |||
| 1290 | } | 1293 | } |
| 1291 | } | 1294 | } |
| 1292 | 1295 | ||
| 1293 | void RasterizerOpenGL::SyncTransformFeedback() { | ||
| 1294 | const auto& regs = system.GPU().Maxwell3D().regs; | ||
| 1295 | UNIMPLEMENTED_IF_MSG(regs.tfb_enabled != 0, "Transform feedbacks are not implemented"); | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | void RasterizerOpenGL::SyncPointState() { | 1296 | void RasterizerOpenGL::SyncPointState() { |
| 1299 | auto& gpu = system.GPU().Maxwell3D(); | 1297 | auto& gpu = system.GPU().Maxwell3D(); |
| 1300 | auto& flags = gpu.dirty.flags; | 1298 | auto& flags = gpu.dirty.flags; |
| @@ -1370,4 +1368,62 @@ void RasterizerOpenGL::SyncFramebufferSRGB() { | |||
| 1370 | oglEnable(GL_FRAMEBUFFER_SRGB, gpu.regs.framebuffer_srgb); | 1368 | oglEnable(GL_FRAMEBUFFER_SRGB, gpu.regs.framebuffer_srgb); |
| 1371 | } | 1369 | } |
| 1372 | 1370 | ||
| 1371 | void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { | ||
| 1372 | const auto& regs = system.GPU().Maxwell3D().regs; | ||
| 1373 | if (regs.tfb_enabled == 0) { | ||
| 1374 | return; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || | ||
| 1378 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || | ||
| 1379 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry)); | ||
| 1380 | |||
| 1381 | for (std::size_t index = 0; index < Maxwell::NumTransformFeedbackBuffers; ++index) { | ||
| 1382 | const auto& binding = regs.tfb_bindings[index]; | ||
| 1383 | if (!binding.buffer_enable) { | ||
| 1384 | if (enabled_transform_feedback_buffers[index]) { | ||
| 1385 | glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), 0, 0, | ||
| 1386 | 0); | ||
| 1387 | } | ||
| 1388 | enabled_transform_feedback_buffers[index] = false; | ||
| 1389 | continue; | ||
| 1390 | } | ||
| 1391 | enabled_transform_feedback_buffers[index] = true; | ||
| 1392 | |||
| 1393 | auto& tfb_buffer = transform_feedback_buffers[index]; | ||
| 1394 | tfb_buffer.Create(); | ||
| 1395 | |||
| 1396 | const GLuint handle = tfb_buffer.handle; | ||
| 1397 | const std::size_t size = binding.buffer_size; | ||
| 1398 | glNamedBufferData(handle, static_cast<GLsizeiptr>(size), nullptr, GL_STREAM_COPY); | ||
| 1399 | glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, static_cast<GLuint>(index), handle, 0, | ||
| 1400 | static_cast<GLsizeiptr>(size)); | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | glBeginTransformFeedback(GL_POINTS); | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | void RasterizerOpenGL::EndTransformFeedback() { | ||
| 1407 | const auto& regs = system.GPU().Maxwell3D().regs; | ||
| 1408 | if (regs.tfb_enabled == 0) { | ||
| 1409 | return; | ||
| 1410 | } | ||
| 1411 | |||
| 1412 | glEndTransformFeedback(); | ||
| 1413 | |||
| 1414 | for (std::size_t index = 0; index < Maxwell::NumTransformFeedbackBuffers; ++index) { | ||
| 1415 | const auto& binding = regs.tfb_bindings[index]; | ||
| 1416 | if (!binding.buffer_enable) { | ||
| 1417 | continue; | ||
| 1418 | } | ||
| 1419 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); | ||
| 1420 | |||
| 1421 | const GLuint handle = transform_feedback_buffers[index].handle; | ||
| 1422 | const GPUVAddr gpu_addr = binding.Address(); | ||
| 1423 | const std::size_t size = binding.buffer_size; | ||
| 1424 | const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | ||
| 1425 | glCopyNamedBufferSubData(handle, *dest_buffer, 0, offset, static_cast<GLsizeiptr>(size)); | ||
| 1426 | } | ||
| 1427 | } | ||
| 1428 | |||
| 1373 | } // namespace OpenGL | 1429 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index e6424f5d2..2d3be2437 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -168,9 +168,6 @@ private: | |||
| 168 | /// Syncs the scissor test state to match the guest state | 168 | /// Syncs the scissor test state to match the guest state |
| 169 | void SyncScissorTest(); | 169 | void SyncScissorTest(); |
| 170 | 170 | ||
| 171 | /// Syncs the transform feedback state to match the guest state | ||
| 172 | void SyncTransformFeedback(); | ||
| 173 | |||
| 174 | /// Syncs the point state to match the guest state | 171 | /// Syncs the point state to match the guest state |
| 175 | void SyncPointState(); | 172 | void SyncPointState(); |
| 176 | 173 | ||
| @@ -192,6 +189,12 @@ private: | |||
| 192 | /// Syncs the framebuffer sRGB state to match the guest state | 189 | /// Syncs the framebuffer sRGB state to match the guest state |
| 193 | void SyncFramebufferSRGB(); | 190 | void SyncFramebufferSRGB(); |
| 194 | 191 | ||
| 192 | /// Begin a transform feedback | ||
| 193 | void BeginTransformFeedback(GLenum primitive_mode); | ||
| 194 | |||
| 195 | /// End a transform feedback | ||
| 196 | void EndTransformFeedback(); | ||
| 197 | |||
| 195 | /// Check for extension that are not strictly required but are needed for correct emulation | 198 | /// Check for extension that are not strictly required but are needed for correct emulation |
| 196 | void CheckExtensions(); | 199 | void CheckExtensions(); |
| 197 | 200 | ||
| @@ -229,6 +232,11 @@ private: | |||
| 229 | BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; | 232 | BindBuffersRangePushBuffer bind_ubo_pushbuffer{GL_UNIFORM_BUFFER}; |
| 230 | BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; | 233 | BindBuffersRangePushBuffer bind_ssbo_pushbuffer{GL_SHADER_STORAGE_BUFFER}; |
| 231 | 234 | ||
| 235 | std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> | ||
| 236 | transform_feedback_buffers; | ||
| 237 | std::bitset<Tegra::Engines::Maxwell3D::Regs::NumTransformFeedbackBuffers> | ||
| 238 | enabled_transform_feedback_buffers; | ||
| 239 | |||
| 232 | /// Number of commands queued to the OpenGL driver. Reseted on flush. | 240 | /// Number of commands queued to the OpenGL driver. Reseted on flush. |
| 233 | std::size_t num_queued_commands = 0; | 241 | std::size_t num_queued_commands = 0; |
| 234 | 242 | ||