Bladeren bron

Merge pull request #12415 from ameerj/ogl-draw-auto

gl_rasterizer: Implement DrawTransformFeedback macro
liamwhite 2 jaren geleden
bovenliggende
commit
ad049f13aa

+ 5 - 2
src/video_core/macro/macro_hle.cpp

@@ -327,12 +327,13 @@ public:
     explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {}
     explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {}
 
 
     void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override {
     void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override {
+        const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback();
+
         auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU);
         auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU);
-        if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) {
+        if (!force && (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology))) {
             Fallback(parameters);
             Fallback(parameters);
             return;
             return;
         }
         }
-
         auto& params = maxwell3d.draw_manager->GetIndirectParams();
         auto& params = maxwell3d.draw_manager->GetIndirectParams();
         params.is_byte_count = true;
         params.is_byte_count = true;
         params.is_indexed = false;
         params.is_indexed = false;
@@ -503,6 +504,8 @@ public:
         maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true);
         maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true);
         maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)),
         maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)),
                              regs.transform_feedback.controls[0].stride, true);
                              regs.transform_feedback.controls[0].stride, true);
+
+        maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address());
     }
     }
 };
 };
 
 

+ 8 - 0
src/video_core/rasterizer_interface.h

@@ -173,5 +173,13 @@ public:
     virtual void BindChannel(Tegra::Control::ChannelState& channel) {}
     virtual void BindChannel(Tegra::Control::ChannelState& channel) {}
 
 
     virtual void ReleaseChannel(s32 channel_id) {}
     virtual void ReleaseChannel(s32 channel_id) {}
+
+    /// Register the address as a Transform Feedback Object
+    virtual void RegisterTransformFeedback(GPUVAddr tfb_object_addr) {}
+
+    /// Returns true when the rasterizer has Draw Transform Feedback capabilities
+    virtual bool HasDrawTransformFeedback() {
+        return false;
+    }
 };
 };
 } // namespace VideoCore
 } // namespace VideoCore

+ 11 - 0
src/video_core/renderer_opengl/gl_buffer_cache.cpp

@@ -376,4 +376,15 @@ void BufferCacheRuntime::BindImageBuffer(Buffer& buffer, u32 offset, u32 size, P
     *image_handles++ = buffer.View(offset, size, format);
     *image_handles++ = buffer.View(offset, size, format);
 }
 }
 
 
+void BufferCacheRuntime::BindTransformFeedbackObject(GPUVAddr tfb_object_addr) {
+    OGLTransformFeedback& tfb_object = tfb_objects[tfb_object_addr];
+    tfb_object.Create();
+    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfb_object.handle);
+}
+
+GLuint BufferCacheRuntime::GetTransformFeedbackObject(GPUVAddr tfb_object_addr) {
+    ASSERT(tfb_objects.contains(tfb_object_addr));
+    return tfb_objects[tfb_object_addr].handle;
+}
+
 } // namespace OpenGL
 } // namespace OpenGL

+ 5 - 0
src/video_core/renderer_opengl/gl_buffer_cache.h

@@ -5,6 +5,7 @@
 
 
 #include <array>
 #include <array>
 #include <span>
 #include <span>
+#include <unordered_map>
 
 
 #include "common/common_types.h"
 #include "common/common_types.h"
 #include "video_core/buffer_cache/buffer_cache_base.h"
 #include "video_core/buffer_cache/buffer_cache_base.h"
@@ -121,6 +122,9 @@ public:
     void BindImageBuffer(Buffer& buffer, u32 offset, u32 size,
     void BindImageBuffer(Buffer& buffer, u32 offset, u32 size,
                          VideoCore::Surface::PixelFormat format);
                          VideoCore::Surface::PixelFormat format);
 
 
+    void BindTransformFeedbackObject(GPUVAddr tfb_object_addr);
+    GLuint GetTransformFeedbackObject(GPUVAddr tfb_object_addr);
+
     u64 GetDeviceMemoryUsage() const;
     u64 GetDeviceMemoryUsage() const;
 
 
     void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) {
     void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) {
@@ -233,6 +237,7 @@ private:
     u32 index_buffer_offset = 0;
     u32 index_buffer_offset = 0;
 
 
     u64 device_access_memory;
     u64 device_access_memory;
+    std::unordered_map<GPUVAddr, OGLTransformFeedback> tfb_objects;
 };
 };
 
 
 struct BufferCacheParams {
 struct BufferCacheParams {

+ 11 - 0
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -309,6 +309,13 @@ void RasterizerOpenGL::DrawIndirect() {
     const auto& params = maxwell3d->draw_manager->GetIndirectParams();
     const auto& params = maxwell3d->draw_manager->GetIndirectParams();
     buffer_cache.SetDrawIndirect(&params);
     buffer_cache.SetDrawIndirect(&params);
     PrepareDraw(params.is_indexed, [this, &params](GLenum primitive_mode) {
     PrepareDraw(params.is_indexed, [this, &params](GLenum primitive_mode) {
+        if (params.is_byte_count) {
+            const GPUVAddr tfb_object_base_addr = params.indirect_start_address - 4U;
+            const GLuint tfb_object =
+                buffer_cache_runtime.GetTransformFeedbackObject(tfb_object_base_addr);
+            glDrawTransformFeedback(primitive_mode, tfb_object);
+            return;
+        }
         const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
         const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer();
         const GLvoid* const gl_offset =
         const GLvoid* const gl_offset =
             reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset));
             reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset));
@@ -1371,6 +1378,10 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
     query_cache.EraseChannel(channel_id);
     query_cache.EraseChannel(channel_id);
 }
 }
 
 
+void RasterizerOpenGL::RegisterTransformFeedback(GPUVAddr tfb_object_addr) {
+    buffer_cache_runtime.BindTransformFeedbackObject(tfb_object_addr);
+}
+
 AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_)
 AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_)
     : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {}
     : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {}
 
 

+ 6 - 0
src/video_core/renderer_opengl/gl_rasterizer.h

@@ -139,6 +139,12 @@ public:
 
 
     void ReleaseChannel(s32 channel_id) override;
     void ReleaseChannel(s32 channel_id) override;
 
 
+    void RegisterTransformFeedback(GPUVAddr tfb_object_addr) override;
+
+    bool HasDrawTransformFeedback() override {
+        return true;
+    }
+
 private:
 private:
     static constexpr size_t MAX_TEXTURES = 192;
     static constexpr size_t MAX_TEXTURES = 192;
     static constexpr size_t MAX_IMAGES = 48;
     static constexpr size_t MAX_IMAGES = 48;

+ 17 - 0
src/video_core/renderer_opengl/gl_resource_manager.cpp

@@ -207,4 +207,21 @@ void OGLQuery::Release() {
     handle = 0;
     handle = 0;
 }
 }
 
 
+void OGLTransformFeedback::Create() {
+    if (handle != 0)
+        return;
+
+    MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
+    glCreateTransformFeedbacks(1, &handle);
+}
+
+void OGLTransformFeedback::Release() {
+    if (handle == 0)
+        return;
+
+    MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
+    glDeleteTransformFeedbacks(1, &handle);
+    handle = 0;
+}
+
 } // namespace OpenGL
 } // namespace OpenGL

+ 27 - 0
src/video_core/renderer_opengl/gl_resource_manager.h

@@ -323,4 +323,31 @@ public:
     GLuint handle = 0;
     GLuint handle = 0;
 };
 };
 
 
+class OGLTransformFeedback final {
+public:
+    YUZU_NON_COPYABLE(OGLTransformFeedback);
+
+    OGLTransformFeedback() = default;
+
+    OGLTransformFeedback(OGLTransformFeedback&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
+
+    ~OGLTransformFeedback() {
+        Release();
+    }
+
+    OGLTransformFeedback& operator=(OGLTransformFeedback&& o) noexcept {
+        Release();
+        handle = std::exchange(o.handle, 0);
+        return *this;
+    }
+
+    /// Creates a new internal OpenGL resource and stores the handle
+    void Create();
+
+    /// Deletes the internal OpenGL resource
+    void Release();
+
+    GLuint handle = 0;
+};
+
 } // namespace OpenGL
 } // namespace OpenGL