From 1eccf67b1ca5bf5e320247d1ed59fd5fcc41ca3d Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Fri, 22 Dec 2023 19:51:46 +0100 Subject: [PATCH] early-access version 4032 --- README.md | 2 +- src/video_core/macro/macro_hle.cpp | 7 +++-- src/video_core/rasterizer_interface.h | 8 ++++++ .../renderer_opengl/gl_buffer_cache.cpp | 11 ++++++++ .../renderer_opengl/gl_buffer_cache.h | 5 ++++ .../renderer_opengl/gl_rasterizer.cpp | 11 ++++++++ .../renderer_opengl/gl_rasterizer.h | 6 +++++ .../renderer_opengl/gl_resource_manager.cpp | 17 ++++++++++++ .../renderer_opengl/gl_resource_manager.h | 27 +++++++++++++++++++ 9 files changed, 91 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14d92a4f2..2e622b8ab 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4031. +This is the source code for early-access 4032. ## Legal Notice diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 09f6e2d97..c729ffbab 100755 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -327,12 +327,13 @@ public: explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} void Execute(const std::vector& parameters, [[maybe_unused]] u32 method) override { + const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback(); + auto topology = static_cast(parameters[0] & 0xFFFFU); - if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { + if (!force && (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology))) { Fallback(parameters); return; } - auto& params = maxwell3d.draw_manager->GetIndirectParams(); params.is_byte_count = true; params.is_indexed = false; @@ -503,6 +504,8 @@ public: maxwell3d.CallMethod(static_cast(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); maxwell3d.CallMethod(static_cast(MAXWELL3D_REG_INDEX(inline_data)), regs.transform_feedback.controls[0].stride, true); + + maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address()); } }; diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 06b538b3b..d17a0af9a 100755 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -173,5 +173,13 @@ public: virtual void BindChannel(Tegra::Control::ChannelState& channel) {} 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 diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index ba28087de..0863cc9f0 100755 --- 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 *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 diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index affcaff04..8626ed010 100755 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h @@ -5,6 +5,7 @@ #include #include +#include #include "common/common_types.h" #include "video_core/buffer_cache/buffer_cache_base.h" @@ -121,6 +122,9 @@ public: void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, VideoCore::Surface::PixelFormat format); + void BindTransformFeedbackObject(GPUVAddr tfb_object_addr); + GLuint GetTransformFeedbackObject(GPUVAddr tfb_object_addr); + u64 GetDeviceMemoryUsage() const; void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { @@ -233,6 +237,7 @@ private: u32 index_buffer_offset = 0; u64 device_access_memory; + std::unordered_map tfb_objects; }; struct BufferCacheParams { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 760af262b..378b38033 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -309,6 +309,13 @@ void RasterizerOpenGL::DrawIndirect() { const auto& params = maxwell3d->draw_manager->GetIndirectParams(); buffer_cache.SetDrawIndirect(¶ms); PrepareDraw(params.is_indexed, [this, ¶ms](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 GLvoid* const gl_offset = reinterpret_cast(static_cast(offset)); @@ -1371,6 +1378,10 @@ void RasterizerOpenGL::ReleaseChannel(s32 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_) : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {} diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 15d371215..7c6cb1365 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -139,6 +139,12 @@ public: void ReleaseChannel(s32 channel_id) override; + void RegisterTransformFeedback(GPUVAddr tfb_object_addr) override; + + bool HasDrawTransformFeedback() override { + return true; + } + private: static constexpr size_t MAX_TEXTURES = 192; 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 0a097667f..751273b71 100755 --- 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() { 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 diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index b743ff179..81c96c23d 100755 --- 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: 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