diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_device.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 90 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 6 |
4 files changed, 98 insertions, 5 deletions
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index a14641b97..890fc6c63 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -214,7 +214,8 @@ Device::Device() | |||
| 214 | has_precise_bug = TestPreciseBug(); | 214 | has_precise_bug = TestPreciseBug(); |
| 215 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | 215 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; |
| 216 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && | 216 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && |
| 217 | GLAD_GL_NV_compute_program5; | 217 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && |
| 218 | GLAD_GL_NV_transform_feedback2; | ||
| 218 | 219 | ||
| 219 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); | 220 | LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); |
| 220 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); | 221 | LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 55e79aaf6..f802fd384 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -93,6 +93,34 @@ std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buffer, | |||
| 93 | return buffer.size; | 93 | return buffer.size; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | /// Translates hardware transform feedback indices | ||
| 97 | /// @param location Hardware location | ||
| 98 | /// @return Pair of ARB_transform_feedback3 token stream first and third arguments | ||
| 99 | /// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt | ||
| 100 | std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) { | ||
| 101 | const u8 index = location / 4; | ||
| 102 | if (index >= 8 && index <= 39) { | ||
| 103 | return {GL_GENERIC_ATTRIB_NV, index - 8}; | ||
| 104 | } | ||
| 105 | if (index >= 48 && index <= 55) { | ||
| 106 | return {GL_TEXTURE_COORD_NV, index - 48}; | ||
| 107 | } | ||
| 108 | switch (index) { | ||
| 109 | case 7: | ||
| 110 | return {GL_POSITION, 0}; | ||
| 111 | case 40: | ||
| 112 | return {GL_PRIMARY_COLOR_NV, 0}; | ||
| 113 | case 41: | ||
| 114 | return {GL_SECONDARY_COLOR_NV, 0}; | ||
| 115 | case 42: | ||
| 116 | return {GL_BACK_PRIMARY_COLOR_NV, 0}; | ||
| 117 | case 43: | ||
| 118 | return {GL_BACK_SECONDARY_COLOR_NV, 0}; | ||
| 119 | } | ||
| 120 | UNIMPLEMENTED_MSG("index={}", static_cast<int>(index)); | ||
| 121 | return {GL_POSITION, 0}; | ||
| 122 | } | ||
| 123 | |||
| 96 | void oglEnable(GLenum cap, bool state) { | 124 | void oglEnable(GLenum cap, bool state) { |
| 97 | (state ? glEnable : glDisable)(cap); | 125 | (state ? glEnable : glDisable)(cap); |
| 98 | } | 126 | } |
| @@ -1547,12 +1575,70 @@ void RasterizerOpenGL::SyncFramebufferSRGB() { | |||
| 1547 | oglEnable(GL_FRAMEBUFFER_SRGB, gpu.regs.framebuffer_srgb); | 1575 | oglEnable(GL_FRAMEBUFFER_SRGB, gpu.regs.framebuffer_srgb); |
| 1548 | } | 1576 | } |
| 1549 | 1577 | ||
| 1578 | void RasterizerOpenGL::SyncTransformFeedback() { | ||
| 1579 | // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal | ||
| 1580 | // when this is required. | ||
| 1581 | const auto& regs = system.GPU().Maxwell3D().regs; | ||
| 1582 | |||
| 1583 | static constexpr std::size_t STRIDE = 3; | ||
| 1584 | std::array<GLint, 128 * STRIDE * Maxwell::NumTransformFeedbackBuffers> attribs; | ||
| 1585 | std::array<GLint, Maxwell::NumTransformFeedbackBuffers> streams; | ||
| 1586 | |||
| 1587 | GLint* cursor = attribs.data(); | ||
| 1588 | GLint* current_stream = streams.data(); | ||
| 1589 | |||
| 1590 | for (std::size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { | ||
| 1591 | const auto& layout = regs.tfb_layouts[feedback]; | ||
| 1592 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); | ||
| 1593 | if (layout.varying_count == 0) { | ||
| 1594 | continue; | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | *current_stream = static_cast<GLint>(feedback); | ||
| 1598 | if (current_stream != streams.data()) { | ||
| 1599 | // When stepping one stream, push the expected token | ||
| 1600 | cursor[0] = GL_NEXT_BUFFER_NV; | ||
| 1601 | cursor[1] = 0; | ||
| 1602 | cursor[2] = 0; | ||
| 1603 | cursor += STRIDE; | ||
| 1604 | } | ||
| 1605 | ++current_stream; | ||
| 1606 | |||
| 1607 | const auto& locations = regs.tfb_varying_locs[feedback]; | ||
| 1608 | std::optional<u8> current_index; | ||
| 1609 | for (u32 offset = 0; offset < layout.varying_count; ++offset) { | ||
| 1610 | const u8 location = locations[offset]; | ||
| 1611 | const u8 index = location / 4; | ||
| 1612 | |||
| 1613 | if (current_index == index) { | ||
| 1614 | // Increase number of components of the previous attachment | ||
| 1615 | ++cursor[-2]; | ||
| 1616 | continue; | ||
| 1617 | } | ||
| 1618 | current_index = index; | ||
| 1619 | |||
| 1620 | std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location); | ||
| 1621 | cursor[1] = 1; | ||
| 1622 | cursor += STRIDE; | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | |||
| 1626 | const GLsizei num_attribs = static_cast<GLsizei>((cursor - attribs.data()) / STRIDE); | ||
| 1627 | const GLsizei num_strides = static_cast<GLsizei>(current_stream - streams.data()); | ||
| 1628 | glTransformFeedbackStreamAttribsNV(num_attribs, attribs.data(), num_strides, streams.data(), | ||
| 1629 | GL_INTERLEAVED_ATTRIBS); | ||
| 1630 | } | ||
| 1631 | |||
| 1550 | void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { | 1632 | void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { |
| 1551 | const auto& regs = system.GPU().Maxwell3D().regs; | 1633 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 1552 | if (regs.tfb_enabled == 0) { | 1634 | if (regs.tfb_enabled == 0) { |
| 1553 | return; | 1635 | return; |
| 1554 | } | 1636 | } |
| 1555 | 1637 | ||
| 1638 | if (device.UseAssemblyShaders()) { | ||
| 1639 | SyncTransformFeedback(); | ||
| 1640 | } | ||
| 1641 | |||
| 1556 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || | 1642 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || |
| 1557 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || | 1643 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || |
| 1558 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry)); | 1644 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry)); |
| @@ -1579,6 +1665,10 @@ void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { | |||
| 1579 | static_cast<GLsizeiptr>(size)); | 1665 | static_cast<GLsizeiptr>(size)); |
| 1580 | } | 1666 | } |
| 1581 | 1667 | ||
| 1668 | // We may have to call BeginTransformFeedbackNV here since they seem to call different | ||
| 1669 | // implementations on Nvidia's driver (the pointer is different) but we are using | ||
| 1670 | // ARB_transform_feedback3 features with NV_transform_feedback interactions and the ARB | ||
| 1671 | // extension doesn't define BeginTransformFeedback (without NV) interactions. It just works. | ||
| 1582 | glBeginTransformFeedback(GL_POINTS); | 1672 | glBeginTransformFeedback(GL_POINTS); |
| 1583 | } | 1673 | } |
| 1584 | 1674 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index f5dc56a0e..7abc8fdbd 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -202,6 +202,10 @@ private: | |||
| 202 | /// Syncs the framebuffer sRGB state to match the guest state | 202 | /// Syncs the framebuffer sRGB state to match the guest state |
| 203 | void SyncFramebufferSRGB(); | 203 | void SyncFramebufferSRGB(); |
| 204 | 204 | ||
| 205 | /// Syncs transform feedback state to match guest state | ||
| 206 | /// @note Only valid on assembly shaders | ||
| 207 | void SyncTransformFeedback(); | ||
| 208 | |||
| 205 | /// Begin a transform feedback | 209 | /// Begin a transform feedback |
| 206 | void BeginTransformFeedback(GLenum primitive_mode); | 210 | void BeginTransformFeedback(GLenum primitive_mode); |
| 207 | 211 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e7952924a..6214fcbc3 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -751,11 +751,9 @@ void RendererOpenGL::RenderScreenshot() { | |||
| 751 | } | 751 | } |
| 752 | 752 | ||
| 753 | bool RendererOpenGL::Init() { | 753 | bool RendererOpenGL::Init() { |
| 754 | if (GLAD_GL_KHR_debug) { | 754 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { |
| 755 | glEnable(GL_DEBUG_OUTPUT); | 755 | glEnable(GL_DEBUG_OUTPUT); |
| 756 | if (Settings::values.renderer_debug) { | 756 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); |
| 757 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | ||
| 758 | } | ||
| 759 | glDebugMessageCallback(DebugHandler, nullptr); | 757 | glDebugMessageCallback(DebugHandler, nullptr); |
| 760 | } | 758 | } |
| 761 | 759 | ||