diff options
| author | 2021-05-21 18:17:53 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:33 -0400 | |
| commit | 6bc54e12a0d274beee0cb7584f73429112ec98b2 (patch) | |
| tree | 76d875eebeb3de8380a6071366e92995d1b1df80 /src | |
| parent | video_core: Abstract transform feedback translation utility (diff) | |
| download | yuzu-6bc54e12a0d274beee0cb7584f73429112ec98b2.tar.gz yuzu-6bc54e12a0d274beee0cb7584f73429112ec98b2.tar.xz yuzu-6bc54e12a0d274beee0cb7584f73429112ec98b2.zip | |
glasm: Set transform feedback state
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_program.cpp | 90 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_program.h | 32 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 98 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 19 |
5 files changed, 132 insertions, 113 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_program.cpp b/src/video_core/renderer_opengl/gl_graphics_program.cpp index b5d75aa13..9677a3ed6 100644 --- a/src/video_core/renderer_opengl/gl_graphics_program.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_program.cpp | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include "video_core/texture_cache/texture_cache.h" | 12 | #include "video_core/texture_cache/texture_cache.h" |
| 13 | 13 | ||
| 14 | namespace OpenGL { | 14 | namespace OpenGL { |
| 15 | 15 | namespace { | |
| 16 | using Shader::ImageBufferDescriptor; | 16 | using Shader::ImageBufferDescriptor; |
| 17 | using Tegra::Texture::TexturePair; | 17 | using Tegra::Texture::TexturePair; |
| 18 | using VideoCommon::ImageId; | 18 | using VideoCommon::ImageId; |
| @@ -20,6 +20,35 @@ using VideoCommon::ImageId; | |||
| 20 | constexpr u32 MAX_TEXTURES = 64; | 20 | constexpr u32 MAX_TEXTURES = 64; |
| 21 | constexpr u32 MAX_IMAGES = 8; | 21 | constexpr u32 MAX_IMAGES = 8; |
| 22 | 22 | ||
| 23 | /// Translates hardware transform feedback indices | ||
| 24 | /// @param location Hardware location | ||
| 25 | /// @return Pair of ARB_transform_feedback3 token stream first and third arguments | ||
| 26 | /// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt | ||
| 27 | std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) { | ||
| 28 | const u8 index = location / 4; | ||
| 29 | if (index >= 8 && index <= 39) { | ||
| 30 | return {GL_GENERIC_ATTRIB_NV, index - 8}; | ||
| 31 | } | ||
| 32 | if (index >= 48 && index <= 55) { | ||
| 33 | return {GL_TEXTURE_COORD_NV, index - 48}; | ||
| 34 | } | ||
| 35 | switch (index) { | ||
| 36 | case 7: | ||
| 37 | return {GL_POSITION, 0}; | ||
| 38 | case 40: | ||
| 39 | return {GL_PRIMARY_COLOR_NV, 0}; | ||
| 40 | case 41: | ||
| 41 | return {GL_SECONDARY_COLOR_NV, 0}; | ||
| 42 | case 42: | ||
| 43 | return {GL_BACK_PRIMARY_COLOR_NV, 0}; | ||
| 44 | case 43: | ||
| 45 | return {GL_BACK_SECONDARY_COLOR_NV, 0}; | ||
| 46 | } | ||
| 47 | UNIMPLEMENTED_MSG("index={}", index); | ||
| 48 | return {GL_POSITION, 0}; | ||
| 49 | } | ||
| 50 | } // Anonymous namespace | ||
| 51 | |||
| 23 | size_t GraphicsProgramKey::Hash() const noexcept { | 52 | size_t GraphicsProgramKey::Hash() const noexcept { |
| 24 | return static_cast<size_t>(Common::CityHash64(reinterpret_cast<const char*>(this), Size())); | 53 | return static_cast<size_t>(Common::CityHash64(reinterpret_cast<const char*>(this), Size())); |
| 25 | } | 54 | } |
| @@ -34,7 +63,8 @@ GraphicsProgram::GraphicsProgram(TextureCache& texture_cache_, BufferCache& buff | |||
| 34 | ProgramManager& program_manager_, StateTracker& state_tracker_, | 63 | ProgramManager& program_manager_, StateTracker& state_tracker_, |
| 35 | OGLProgram program_, | 64 | OGLProgram program_, |
| 36 | std::array<OGLAssemblyProgram, 5> assembly_programs_, | 65 | std::array<OGLAssemblyProgram, 5> assembly_programs_, |
| 37 | const std::array<const Shader::Info*, 5>& infos) | 66 | const std::array<const Shader::Info*, 5>& infos, |
| 67 | const VideoCommon::TransformFeedbackState* xfb_state) | ||
| 38 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, | 68 | : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, |
| 39 | gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, | 69 | gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_}, |
| 40 | state_tracker{state_tracker_}, program{std::move(program_)}, assembly_programs{std::move( | 70 | state_tracker{state_tracker_}, program{std::move(program_)}, assembly_programs{std::move( |
| @@ -74,6 +104,10 @@ GraphicsProgram::GraphicsProgram(TextureCache& texture_cache_, BufferCache& buff | |||
| 74 | } | 104 | } |
| 75 | ASSERT(num_textures <= MAX_TEXTURES); | 105 | ASSERT(num_textures <= MAX_TEXTURES); |
| 76 | ASSERT(num_images <= MAX_IMAGES); | 106 | ASSERT(num_images <= MAX_IMAGES); |
| 107 | |||
| 108 | if (assembly_programs[0].handle != 0 && xfb_state) { | ||
| 109 | GenerateTransformFeedbackState(*xfb_state); | ||
| 110 | } | ||
| 77 | } | 111 | } |
| 78 | 112 | ||
| 79 | struct Spec { | 113 | struct Spec { |
| @@ -302,4 +336,56 @@ void GraphicsProgram::Configure(bool is_indexed) { | |||
| 302 | } | 336 | } |
| 303 | } | 337 | } |
| 304 | 338 | ||
| 339 | void GraphicsProgram::GenerateTransformFeedbackState( | ||
| 340 | const VideoCommon::TransformFeedbackState& xfb_state) { | ||
| 341 | // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal | ||
| 342 | // when this is required. | ||
| 343 | const auto& regs{maxwell3d.regs}; | ||
| 344 | |||
| 345 | GLint* cursor{xfb_attribs.data()}; | ||
| 346 | GLint* current_stream{xfb_streams.data()}; | ||
| 347 | |||
| 348 | for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { | ||
| 349 | const auto& layout = regs.tfb_layouts[feedback]; | ||
| 350 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); | ||
| 351 | if (layout.varying_count == 0) { | ||
| 352 | continue; | ||
| 353 | } | ||
| 354 | *current_stream = static_cast<GLint>(feedback); | ||
| 355 | if (current_stream != xfb_streams.data()) { | ||
| 356 | // When stepping one stream, push the expected token | ||
| 357 | cursor[0] = GL_NEXT_BUFFER_NV; | ||
| 358 | cursor[1] = 0; | ||
| 359 | cursor[2] = 0; | ||
| 360 | cursor += XFB_ENTRY_STRIDE; | ||
| 361 | } | ||
| 362 | ++current_stream; | ||
| 363 | |||
| 364 | const auto& locations = regs.tfb_varying_locs[feedback]; | ||
| 365 | std::optional<u8> current_index; | ||
| 366 | for (u32 offset = 0; offset < layout.varying_count; ++offset) { | ||
| 367 | const u8 location = locations[offset]; | ||
| 368 | const u8 index = location / 4; | ||
| 369 | |||
| 370 | if (current_index == index) { | ||
| 371 | // Increase number of components of the previous attachment | ||
| 372 | ++cursor[-2]; | ||
| 373 | continue; | ||
| 374 | } | ||
| 375 | current_index = index; | ||
| 376 | |||
| 377 | std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location); | ||
| 378 | cursor[1] = 1; | ||
| 379 | cursor += XFB_ENTRY_STRIDE; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | num_xfb_attribs = static_cast<GLsizei>((cursor - xfb_attribs.data()) / XFB_ENTRY_STRIDE); | ||
| 383 | num_xfb_strides = static_cast<GLsizei>(current_stream - xfb_streams.data()); | ||
| 384 | } | ||
| 385 | |||
| 386 | void GraphicsProgram::ConfigureTransformFeedbackImpl() const { | ||
| 387 | glTransformFeedbackStreamAttribsNV(num_xfb_attribs, xfb_attribs.data(), num_xfb_strides, | ||
| 388 | xfb_streams.data(), GL_INTERLEAVED_ATTRIBS); | ||
| 389 | } | ||
| 390 | |||
| 305 | } // namespace OpenGL | 391 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_graphics_program.h b/src/video_core/renderer_opengl/gl_graphics_program.h index 18292bb16..53a57ede5 100644 --- a/src/video_core/renderer_opengl/gl_graphics_program.h +++ b/src/video_core/renderer_opengl/gl_graphics_program.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 16 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| 17 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 17 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 18 | #include "video_core/renderer_opengl/gl_texture_cache.h" | 18 | #include "video_core/renderer_opengl/gl_texture_cache.h" |
| 19 | #include "video_core/transform_feedback.h" | ||
| 19 | 20 | ||
| 20 | namespace OpenGL { | 21 | namespace OpenGL { |
| 21 | 22 | ||
| @@ -24,16 +25,6 @@ class ProgramManager; | |||
| 24 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 25 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 25 | 26 | ||
| 26 | struct GraphicsProgramKey { | 27 | struct GraphicsProgramKey { |
| 27 | struct TransformFeedbackState { | ||
| 28 | struct Layout { | ||
| 29 | u32 stream; | ||
| 30 | u32 varying_count; | ||
| 31 | u32 stride; | ||
| 32 | }; | ||
| 33 | std::array<Layout, Maxwell::NumTransformFeedbackBuffers> layouts; | ||
| 34 | std::array<std::array<u8, 128>, Maxwell::NumTransformFeedbackBuffers> varyings; | ||
| 35 | }; | ||
| 36 | |||
| 37 | std::array<u64, 6> unique_hashes; | 28 | std::array<u64, 6> unique_hashes; |
| 38 | union { | 29 | union { |
| 39 | u32 raw; | 30 | u32 raw; |
| @@ -45,7 +36,7 @@ struct GraphicsProgramKey { | |||
| 45 | BitField<10, 1, u32> tessellation_clockwise; | 36 | BitField<10, 1, u32> tessellation_clockwise; |
| 46 | }; | 37 | }; |
| 47 | std::array<u32, 3> padding; | 38 | std::array<u32, 3> padding; |
| 48 | TransformFeedbackState xfb_state; | 39 | VideoCommon::TransformFeedbackState xfb_state; |
| 49 | 40 | ||
| 50 | size_t Hash() const noexcept; | 41 | size_t Hash() const noexcept; |
| 51 | 42 | ||
| @@ -75,11 +66,22 @@ public: | |||
| 75 | ProgramManager& program_manager_, StateTracker& state_tracker_, | 66 | ProgramManager& program_manager_, StateTracker& state_tracker_, |
| 76 | OGLProgram program_, | 67 | OGLProgram program_, |
| 77 | std::array<OGLAssemblyProgram, 5> assembly_programs_, | 68 | std::array<OGLAssemblyProgram, 5> assembly_programs_, |
| 78 | const std::array<const Shader::Info*, 5>& infos); | 69 | const std::array<const Shader::Info*, 5>& infos, |
| 70 | const VideoCommon::TransformFeedbackState* xfb_state); | ||
| 79 | 71 | ||
| 80 | void Configure(bool is_indexed); | 72 | void Configure(bool is_indexed); |
| 81 | 73 | ||
| 74 | void ConfigureTransformFeedback() const { | ||
| 75 | if (num_xfb_attribs != 0) { | ||
| 76 | ConfigureTransformFeedbackImpl(); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 82 | private: | 80 | private: |
| 81 | void GenerateTransformFeedbackState(const VideoCommon::TransformFeedbackState& xfb_state); | ||
| 82 | |||
| 83 | void ConfigureTransformFeedbackImpl() const; | ||
| 84 | |||
| 83 | TextureCache& texture_cache; | 85 | TextureCache& texture_cache; |
| 84 | BufferCache& buffer_cache; | 86 | BufferCache& buffer_cache; |
| 85 | Tegra::MemoryManager& gpu_memory; | 87 | Tegra::MemoryManager& gpu_memory; |
| @@ -96,6 +98,12 @@ private: | |||
| 96 | std::array<u32, 5> base_storage_bindings{}; | 98 | std::array<u32, 5> base_storage_bindings{}; |
| 97 | std::array<u32, 5> num_texture_buffers{}; | 99 | std::array<u32, 5> num_texture_buffers{}; |
| 98 | std::array<u32, 5> num_image_buffers{}; | 100 | std::array<u32, 5> num_image_buffers{}; |
| 101 | |||
| 102 | static constexpr std::size_t XFB_ENTRY_STRIDE = 3; | ||
| 103 | GLsizei num_xfb_attribs{}; | ||
| 104 | GLsizei num_xfb_strides{}; | ||
| 105 | std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{}; | ||
| 106 | std::array<GLint, Maxwell::NumTransformFeedbackBuffers> xfb_streams{}; | ||
| 99 | }; | 107 | }; |
| 100 | 108 | ||
| 101 | } // namespace OpenGL | 109 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4834d58f0..51ff42ee9 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -51,37 +51,8 @@ MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(128, 128, 192)); | |||
| 51 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB(100, 255, 100)); | 51 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB(100, 255, 100)); |
| 52 | 52 | ||
| 53 | namespace { | 53 | namespace { |
| 54 | |||
| 55 | constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16; | 54 | constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16; |
| 56 | 55 | ||
| 57 | /// Translates hardware transform feedback indices | ||
| 58 | /// @param location Hardware location | ||
| 59 | /// @return Pair of ARB_transform_feedback3 token stream first and third arguments | ||
| 60 | /// @note Read https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_transform_feedback3.txt | ||
| 61 | std::pair<GLint, GLint> TransformFeedbackEnum(u8 location) { | ||
| 62 | const u8 index = location / 4; | ||
| 63 | if (index >= 8 && index <= 39) { | ||
| 64 | return {GL_GENERIC_ATTRIB_NV, index - 8}; | ||
| 65 | } | ||
| 66 | if (index >= 48 && index <= 55) { | ||
| 67 | return {GL_TEXTURE_COORD_NV, index - 48}; | ||
| 68 | } | ||
| 69 | switch (index) { | ||
| 70 | case 7: | ||
| 71 | return {GL_POSITION, 0}; | ||
| 72 | case 40: | ||
| 73 | return {GL_PRIMARY_COLOR_NV, 0}; | ||
| 74 | case 41: | ||
| 75 | return {GL_SECONDARY_COLOR_NV, 0}; | ||
| 76 | case 42: | ||
| 77 | return {GL_BACK_PRIMARY_COLOR_NV, 0}; | ||
| 78 | case 43: | ||
| 79 | return {GL_BACK_SECONDARY_COLOR_NV, 0}; | ||
| 80 | } | ||
| 81 | UNIMPLEMENTED_MSG("index={}", index); | ||
| 82 | return {GL_POSITION, 0}; | ||
| 83 | } | ||
| 84 | |||
| 85 | void oglEnable(GLenum cap, bool state) { | 56 | void oglEnable(GLenum cap, bool state) { |
| 86 | (state ? glEnable : glDisable)(cap); | 57 | (state ? glEnable : glDisable)(cap); |
| 87 | } | 58 | } |
| @@ -253,7 +224,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 253 | program->Configure(is_indexed); | 224 | program->Configure(is_indexed); |
| 254 | 225 | ||
| 255 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d.regs.draw.topology); | 226 | const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d.regs.draw.topology); |
| 256 | BeginTransformFeedback(primitive_mode); | 227 | BeginTransformFeedback(program, primitive_mode); |
| 257 | 228 | ||
| 258 | const GLuint base_instance = static_cast<GLuint>(maxwell3d.regs.vb_base_instance); | 229 | const GLuint base_instance = static_cast<GLuint>(maxwell3d.regs.vb_base_instance); |
| 259 | const GLsizei num_instances = | 230 | const GLsizei num_instances = |
| @@ -1025,68 +996,13 @@ void RasterizerOpenGL::SyncFramebufferSRGB() { | |||
| 1025 | oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d.regs.framebuffer_srgb); | 996 | oglEnable(GL_FRAMEBUFFER_SRGB, maxwell3d.regs.framebuffer_srgb); |
| 1026 | } | 997 | } |
| 1027 | 998 | ||
| 1028 | void RasterizerOpenGL::SyncTransformFeedback() { | 999 | void RasterizerOpenGL::BeginTransformFeedback(GraphicsProgram* program, GLenum primitive_mode) { |
| 1029 | // TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal | ||
| 1030 | // when this is required. | ||
| 1031 | const auto& regs = maxwell3d.regs; | ||
| 1032 | |||
| 1033 | static constexpr std::size_t STRIDE = 3; | ||
| 1034 | std::array<GLint, 128 * STRIDE * Maxwell::NumTransformFeedbackBuffers> attribs; | ||
| 1035 | std::array<GLint, Maxwell::NumTransformFeedbackBuffers> streams; | ||
| 1036 | |||
| 1037 | GLint* cursor = attribs.data(); | ||
| 1038 | GLint* current_stream = streams.data(); | ||
| 1039 | |||
| 1040 | for (std::size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) { | ||
| 1041 | const auto& layout = regs.tfb_layouts[feedback]; | ||
| 1042 | UNIMPLEMENTED_IF_MSG(layout.stride != layout.varying_count * 4, "Stride padding"); | ||
| 1043 | if (layout.varying_count == 0) { | ||
| 1044 | continue; | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | *current_stream = static_cast<GLint>(feedback); | ||
| 1048 | if (current_stream != streams.data()) { | ||
| 1049 | // When stepping one stream, push the expected token | ||
| 1050 | cursor[0] = GL_NEXT_BUFFER_NV; | ||
| 1051 | cursor[1] = 0; | ||
| 1052 | cursor[2] = 0; | ||
| 1053 | cursor += STRIDE; | ||
| 1054 | } | ||
| 1055 | ++current_stream; | ||
| 1056 | |||
| 1057 | const auto& locations = regs.tfb_varying_locs[feedback]; | ||
| 1058 | std::optional<u8> current_index; | ||
| 1059 | for (u32 offset = 0; offset < layout.varying_count; ++offset) { | ||
| 1060 | const u8 location = locations[offset]; | ||
| 1061 | const u8 index = location / 4; | ||
| 1062 | |||
| 1063 | if (current_index == index) { | ||
| 1064 | // Increase number of components of the previous attachment | ||
| 1065 | ++cursor[-2]; | ||
| 1066 | continue; | ||
| 1067 | } | ||
| 1068 | current_index = index; | ||
| 1069 | |||
| 1070 | std::tie(cursor[0], cursor[2]) = TransformFeedbackEnum(location); | ||
| 1071 | cursor[1] = 1; | ||
| 1072 | cursor += STRIDE; | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | const GLsizei num_attribs = static_cast<GLsizei>((cursor - attribs.data()) / STRIDE); | ||
| 1077 | const GLsizei num_strides = static_cast<GLsizei>(current_stream - streams.data()); | ||
| 1078 | glTransformFeedbackStreamAttribsNV(num_attribs, attribs.data(), num_strides, streams.data(), | ||
| 1079 | GL_INTERLEAVED_ATTRIBS); | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { | ||
| 1083 | const auto& regs = maxwell3d.regs; | 1000 | const auto& regs = maxwell3d.regs; |
| 1084 | if (regs.tfb_enabled == 0) { | 1001 | if (regs.tfb_enabled == 0) { |
| 1085 | return; | 1002 | return; |
| 1086 | } | 1003 | } |
| 1087 | if (device.UseAssemblyShaders()) { | 1004 | program->ConfigureTransformFeedback(); |
| 1088 | SyncTransformFeedback(); | 1005 | |
| 1089 | } | ||
| 1090 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || | 1006 | UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationControl) || |
| 1091 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || | 1007 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::TesselationEval) || |
| 1092 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry)); | 1008 | regs.IsShaderConfigEnabled(Maxwell::ShaderProgram::Geometry)); |
| @@ -1100,11 +1016,9 @@ void RasterizerOpenGL::BeginTransformFeedback(GLenum primitive_mode) { | |||
| 1100 | } | 1016 | } |
| 1101 | 1017 | ||
| 1102 | void RasterizerOpenGL::EndTransformFeedback() { | 1018 | void RasterizerOpenGL::EndTransformFeedback() { |
| 1103 | const auto& regs = maxwell3d.regs; | 1019 | if (maxwell3d.regs.tfb_enabled != 0) { |
| 1104 | if (regs.tfb_enabled == 0) { | 1020 | glEndTransformFeedback(); |
| 1105 | return; | ||
| 1106 | } | 1021 | } |
| 1107 | glEndTransformFeedback(); | ||
| 1108 | } | 1022 | } |
| 1109 | 1023 | ||
| 1110 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} | 1024 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 2fdcbe4ba..08f509c19 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -193,12 +193,8 @@ private: | |||
| 193 | /// Syncs vertex instances to match the guest state | 193 | /// Syncs vertex instances to match the guest state |
| 194 | void SyncVertexInstances(); | 194 | void SyncVertexInstances(); |
| 195 | 195 | ||
| 196 | /// Syncs transform feedback state to match guest state | ||
| 197 | /// @note Only valid on assembly shaders | ||
| 198 | void SyncTransformFeedback(); | ||
| 199 | |||
| 200 | /// Begin a transform feedback | 196 | /// Begin a transform feedback |
| 201 | void BeginTransformFeedback(GLenum primitive_mode); | 197 | void BeginTransformFeedback(GraphicsProgram* program, GLenum primitive_mode); |
| 202 | 198 | ||
| 203 | /// End a transform feedback | 199 | /// End a transform feedback |
| 204 | void EndTransformFeedback(); | 200 | void EndTransformFeedback(); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index b4f26dd74..0a0f1324f 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -254,6 +254,17 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsProgramKey& key, | |||
| 254 | } | 254 | } |
| 255 | return info; | 255 | return info; |
| 256 | } | 256 | } |
| 257 | |||
| 258 | void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs) { | ||
| 259 | std::ranges::transform(regs.tfb_layouts, state.layouts.begin(), [](const auto& layout) { | ||
| 260 | return VideoCommon::TransformFeedbackState::Layout{ | ||
| 261 | .stream = layout.stream, | ||
| 262 | .varying_count = layout.varying_count, | ||
| 263 | .stride = layout.stride, | ||
| 264 | }; | ||
| 265 | }); | ||
| 266 | state.varyings = regs.tfb_varying_locs; | ||
| 267 | } | ||
| 257 | } // Anonymous namespace | 268 | } // Anonymous namespace |
| 258 | 269 | ||
| 259 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, | 270 | ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, |
| @@ -282,7 +293,10 @@ GraphicsProgram* ShaderCache::CurrentGraphicsProgram() { | |||
| 282 | graphics_key.tessellation_primitive.Assign(regs.tess_mode.prim.Value()); | 293 | graphics_key.tessellation_primitive.Assign(regs.tess_mode.prim.Value()); |
| 283 | graphics_key.tessellation_spacing.Assign(regs.tess_mode.spacing.Value()); | 294 | graphics_key.tessellation_spacing.Assign(regs.tess_mode.spacing.Value()); |
| 284 | graphics_key.tessellation_clockwise.Assign(regs.tess_mode.cw.Value()); | 295 | graphics_key.tessellation_clockwise.Assign(regs.tess_mode.cw.Value()); |
| 285 | 296 | graphics_key.xfb_enabled.Assign(regs.tfb_enabled != 0 ? 1 : 0); | |
| 297 | if (graphics_key.xfb_enabled) { | ||
| 298 | SetXfbState(graphics_key.xfb_state, regs); | ||
| 299 | } | ||
| 286 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; | 300 | const auto [pair, is_new]{graphics_cache.try_emplace(graphics_key)}; |
| 287 | auto& program{pair->second}; | 301 | auto& program{pair->second}; |
| 288 | if (is_new) { | 302 | if (is_new) { |
| @@ -368,7 +382,8 @@ std::unique_ptr<GraphicsProgram> ShaderCache::CreateGraphicsProgram( | |||
| 368 | } | 382 | } |
| 369 | return std::make_unique<GraphicsProgram>( | 383 | return std::make_unique<GraphicsProgram>( |
| 370 | texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, | 384 | texture_cache, buffer_cache, gpu_memory, maxwell3d, program_manager, state_tracker, |
| 371 | std::move(source_program), std::move(assembly_programs), infos); | 385 | std::move(source_program), std::move(assembly_programs), infos, |
| 386 | key.xfb_enabled != 0 ? &key.xfb_state : nullptr); | ||
| 372 | } | 387 | } |
| 373 | 388 | ||
| 374 | std::unique_ptr<ComputeProgram> ShaderCache::CreateComputeProgram( | 389 | std::unique_ptr<ComputeProgram> ShaderCache::CreateComputeProgram( |