diff options
| author | 2023-12-19 16:25:08 -0500 | |
|---|---|---|
| committer | 2023-12-19 19:54:57 -0500 | |
| commit | bbc0ed118df7f64522e198307a6d28607b23d4be (patch) | |
| tree | 2dfd7ecaec445de037ec0af719d12991b88379fd | |
| parent | Merge pull request #12411 from ameerj/gl-nv-tfb-fixups (diff) | |
| download | yuzu-bbc0ed118df7f64522e198307a6d28607b23d4be.tar.gz yuzu-bbc0ed118df7f64522e198307a6d28607b23d4be.tar.xz yuzu-bbc0ed118df7f64522e198307a6d28607b23d4be.zip | |
gl_rasterizer: Implement DrawTransformFeedback macro
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/macro/macro_hle.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/rasterizer_interface.h | 8 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.h | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.h | 27 |
8 files changed, 90 insertions, 2 deletions
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 046c8085e..46e853e04 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -327,12 +327,13 @@ public: | |||
| 327 | explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | 327 | explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 328 | 328 | ||
| 329 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | 329 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { |
| 330 | const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback(); | ||
| 331 | |||
| 330 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU); | 332 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU); |
| 331 | if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { | 333 | if (!force && (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology))) { |
| 332 | Fallback(parameters); | 334 | Fallback(parameters); |
| 333 | return; | 335 | return; |
| 334 | } | 336 | } |
| 335 | |||
| 336 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | 337 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); |
| 337 | params.is_byte_count = true; | 338 | params.is_byte_count = true; |
| 338 | params.is_indexed = false; | 339 | params.is_indexed = false; |
| @@ -503,6 +504,8 @@ public: | |||
| 503 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); | 504 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); |
| 504 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), | 505 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), |
| 505 | regs.transform_feedback.controls[0].stride, true); | 506 | regs.transform_feedback.controls[0].stride, true); |
| 507 | |||
| 508 | maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address()); | ||
| 506 | } | 509 | } |
| 507 | }; | 510 | }; |
| 508 | 511 | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index af1469147..49224ca85 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -173,5 +173,13 @@ public: | |||
| 173 | virtual void BindChannel(Tegra::Control::ChannelState& channel) {} | 173 | virtual void BindChannel(Tegra::Control::ChannelState& channel) {} |
| 174 | 174 | ||
| 175 | virtual void ReleaseChannel(s32 channel_id) {} | 175 | virtual void ReleaseChannel(s32 channel_id) {} |
| 176 | |||
| 177 | /// Register the address as a Transform Feedback Object | ||
| 178 | virtual void RegisterTransformFeedback(GPUVAddr tfb_object_addr) {} | ||
| 179 | |||
| 180 | /// Returns true when the rasterizer has Draw Transform Feedback capabilities | ||
| 181 | virtual bool HasDrawTransformFeedback() { | ||
| 182 | return false; | ||
| 183 | } | ||
| 176 | }; | 184 | }; |
| 177 | } // namespace VideoCore | 185 | } // namespace VideoCore |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index b787b6994..517ac14dd 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -376,4 +376,15 @@ void BufferCacheRuntime::BindImageBuffer(Buffer& buffer, u32 offset, u32 size, P | |||
| 376 | *image_handles++ = buffer.View(offset, size, format); | 376 | *image_handles++ = buffer.View(offset, size, format); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | void BufferCacheRuntime::BindTransformFeedbackObject(GPUVAddr tfb_object_addr) { | ||
| 380 | OGLTransformFeedback& tfb_object = tfb_objects[tfb_object_addr]; | ||
| 381 | tfb_object.Create(); | ||
| 382 | glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfb_object.handle); | ||
| 383 | } | ||
| 384 | |||
| 385 | GLuint BufferCacheRuntime::GetTransformFeedbackObject(GPUVAddr tfb_object_addr) { | ||
| 386 | ASSERT(tfb_objects.contains(tfb_object_addr)); | ||
| 387 | return tfb_objects[tfb_object_addr].handle; | ||
| 388 | } | ||
| 389 | |||
| 379 | } // namespace OpenGL | 390 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 1e8708f59..2c18de166 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <unordered_map> | ||
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "video_core/buffer_cache/buffer_cache_base.h" | 11 | #include "video_core/buffer_cache/buffer_cache_base.h" |
| @@ -121,6 +122,9 @@ public: | |||
| 121 | void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, | 122 | void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, |
| 122 | VideoCore::Surface::PixelFormat format); | 123 | VideoCore::Surface::PixelFormat format); |
| 123 | 124 | ||
| 125 | void BindTransformFeedbackObject(GPUVAddr tfb_object_addr); | ||
| 126 | GLuint GetTransformFeedbackObject(GPUVAddr tfb_object_addr); | ||
| 127 | |||
| 124 | u64 GetDeviceMemoryUsage() const; | 128 | u64 GetDeviceMemoryUsage() const; |
| 125 | 129 | ||
| 126 | void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { | 130 | void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { |
| @@ -233,6 +237,7 @@ private: | |||
| 233 | u32 index_buffer_offset = 0; | 237 | u32 index_buffer_offset = 0; |
| 234 | 238 | ||
| 235 | u64 device_access_memory; | 239 | u64 device_access_memory; |
| 240 | std::unordered_map<GPUVAddr, OGLTransformFeedback> tfb_objects; | ||
| 236 | }; | 241 | }; |
| 237 | 242 | ||
| 238 | struct BufferCacheParams { | 243 | struct BufferCacheParams { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4832c03c5..291515e73 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -294,6 +294,13 @@ void RasterizerOpenGL::DrawIndirect() { | |||
| 294 | const auto& params = maxwell3d->draw_manager->GetIndirectParams(); | 294 | const auto& params = maxwell3d->draw_manager->GetIndirectParams(); |
| 295 | buffer_cache.SetDrawIndirect(¶ms); | 295 | buffer_cache.SetDrawIndirect(¶ms); |
| 296 | PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { | 296 | PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { |
| 297 | if (params.is_byte_count) { | ||
| 298 | const GPUVAddr tfb_object_base_addr = params.indirect_start_address - 4U; | ||
| 299 | const GLuint tfb_object = | ||
| 300 | buffer_cache_runtime.GetTransformFeedbackObject(tfb_object_base_addr); | ||
| 301 | glDrawTransformFeedback(primitive_mode, tfb_object); | ||
| 302 | return; | ||
| 303 | } | ||
| 297 | const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); | 304 | const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); |
| 298 | const GLvoid* const gl_offset = | 305 | const GLvoid* const gl_offset = |
| 299 | reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset)); | 306 | reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset)); |
| @@ -1350,6 +1357,10 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) { | |||
| 1350 | query_cache.EraseChannel(channel_id); | 1357 | query_cache.EraseChannel(channel_id); |
| 1351 | } | 1358 | } |
| 1352 | 1359 | ||
| 1360 | void RasterizerOpenGL::RegisterTransformFeedback(GPUVAddr tfb_object_addr) { | ||
| 1361 | buffer_cache_runtime.BindTransformFeedbackObject(tfb_object_addr); | ||
| 1362 | } | ||
| 1363 | |||
| 1353 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_) | 1364 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_) |
| 1354 | : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {} | 1365 | : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {} |
| 1355 | 1366 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index ceffe1f1e..d28388a9d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -139,6 +139,12 @@ public: | |||
| 139 | 139 | ||
| 140 | void ReleaseChannel(s32 channel_id) override; | 140 | void ReleaseChannel(s32 channel_id) override; |
| 141 | 141 | ||
| 142 | void RegisterTransformFeedback(GPUVAddr tfb_object_addr) override; | ||
| 143 | |||
| 144 | bool HasDrawTransformFeedback() override { | ||
| 145 | return true; | ||
| 146 | } | ||
| 147 | |||
| 142 | private: | 148 | private: |
| 143 | static constexpr size_t MAX_TEXTURES = 192; | 149 | static constexpr size_t MAX_TEXTURES = 192; |
| 144 | static constexpr size_t MAX_IMAGES = 48; | 150 | static constexpr size_t MAX_IMAGES = 48; |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index eae8fd110..1d2c9b70a 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -207,4 +207,21 @@ void OGLQuery::Release() { | |||
| 207 | handle = 0; | 207 | handle = 0; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | void OGLTransformFeedback::Create() { | ||
| 211 | if (handle != 0) | ||
| 212 | return; | ||
| 213 | |||
| 214 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | ||
| 215 | glCreateTransformFeedbacks(1, &handle); | ||
| 216 | } | ||
| 217 | |||
| 218 | void OGLTransformFeedback::Release() { | ||
| 219 | if (handle == 0) | ||
| 220 | return; | ||
| 221 | |||
| 222 | MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); | ||
| 223 | glDeleteTransformFeedbacks(1, &handle); | ||
| 224 | handle = 0; | ||
| 225 | } | ||
| 226 | |||
| 210 | } // namespace OpenGL | 227 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 77362acd2..6ca8227bd 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -323,4 +323,31 @@ public: | |||
| 323 | GLuint handle = 0; | 323 | GLuint handle = 0; |
| 324 | }; | 324 | }; |
| 325 | 325 | ||
| 326 | class OGLTransformFeedback final { | ||
| 327 | public: | ||
| 328 | YUZU_NON_COPYABLE(OGLTransformFeedback); | ||
| 329 | |||
| 330 | OGLTransformFeedback() = default; | ||
| 331 | |||
| 332 | OGLTransformFeedback(OGLTransformFeedback&& o) noexcept : handle(std::exchange(o.handle, 0)) {} | ||
| 333 | |||
| 334 | ~OGLTransformFeedback() { | ||
| 335 | Release(); | ||
| 336 | } | ||
| 337 | |||
| 338 | OGLTransformFeedback& operator=(OGLTransformFeedback&& o) noexcept { | ||
| 339 | Release(); | ||
| 340 | handle = std::exchange(o.handle, 0); | ||
| 341 | return *this; | ||
| 342 | } | ||
| 343 | |||
| 344 | /// Creates a new internal OpenGL resource and stores the handle | ||
| 345 | void Create(); | ||
| 346 | |||
| 347 | /// Deletes the internal OpenGL resource | ||
| 348 | void Release(); | ||
| 349 | |||
| 350 | GLuint handle = 0; | ||
| 351 | }; | ||
| 352 | |||
| 326 | } // namespace OpenGL | 353 | } // namespace OpenGL |