From fd9525acc2598c78f90e59451bfbcc2b12af0e49 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Sat, 4 Feb 2023 12:57:57 +0200 Subject: [PATCH] video_core: Use interval map for cached_pages * Also eliminate g_memory in hardware renderers --- src/video_core/rasterizer_accelerated.cpp | 92 ---------------- src/video_core/rasterizer_accelerated.h | 8 +- .../rasterizer_cache/rasterizer_cache.h | 102 ++++++++++++++---- .../renderer_opengl/gl_rasterizer.cpp | 18 ++-- .../renderer_opengl/gl_rasterizer.h | 9 +- .../renderer_opengl/renderer_opengl.cpp | 14 +-- .../renderer_opengl/renderer_opengl.h | 8 +- .../renderer_vulkan/renderer_vulkan.cpp | 8 +- .../renderer_vulkan/renderer_vulkan.h | 14 ++- .../renderer_vulkan/vk_rasterizer.cpp | 26 +++-- .../renderer_vulkan/vk_rasterizer.h | 13 ++- src/video_core/video_core.cpp | 4 +- 12 files changed, 161 insertions(+), 155 deletions(-) diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 16c60d17e..12b3852d7 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp @@ -88,98 +88,6 @@ void RasterizerAccelerated::AddTriangle(const Pica::Shader::OutputVertex& v0, vertex_batch.emplace_back(v2, AreQuaternionsOpposite(v0.quat, v2.quat)); } -void RasterizerAccelerated::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) { - const u32 page_start = addr >> Memory::CITRA_PAGE_BITS; - const u32 page_end = ((addr + size - 1) >> Memory::CITRA_PAGE_BITS) + 1; - - u32 uncache_start_addr = 0; - u32 cache_start_addr = 0; - u32 uncache_bytes = 0; - u32 cache_bytes = 0; - - for (u32 page = page_start; page != page_end; page++) { - auto& count = cached_pages.at(page); - - // Ensure no overflow happens - if (delta > 0) { - ASSERT_MSG(count < std::numeric_limits::max(), "Count will overflow!"); - } else if (delta < 0) { - ASSERT_MSG(count > 0, "Count will underflow!"); - } else { - ASSERT_MSG(false, "Delta must be non-zero!"); - } - - // Adds or subtracts 1, as count is a unsigned 8-bit value - count += delta; - - // Assume delta is either -1 or 1 - if (count == 0) { - if (uncache_bytes == 0) { - uncache_start_addr = page << Memory::CITRA_PAGE_BITS; - } - - uncache_bytes += Memory::CITRA_PAGE_SIZE; - } else if (uncache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, - false); - uncache_bytes = 0; - } - - if (count == 1 && delta > 0) { - if (cache_bytes == 0) { - cache_start_addr = page << Memory::CITRA_PAGE_BITS; - } - - cache_bytes += Memory::CITRA_PAGE_SIZE; - } else if (cache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes, true); - - cache_bytes = 0; - } - } - - if (uncache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, false); - } - - if (cache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(cache_start_addr, cache_bytes, true); - } -} - -void RasterizerAccelerated::ClearAll(bool flush) { - // Force flush all surfaces from the cache - if (flush) { - FlushRegion(0x0, 0xFFFFFFFF); - } - - u32 uncache_start_addr = 0; - u32 uncache_bytes = 0; - - for (u32 page = 0; page != cached_pages.size(); page++) { - auto& count = cached_pages.at(page); - - // Assume delta is either -1 or 1 - if (count != 0) { - if (uncache_bytes == 0) { - uncache_start_addr = page << Memory::CITRA_PAGE_BITS; - } - - uncache_bytes += Memory::CITRA_PAGE_SIZE; - } else if (uncache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, - false); - uncache_bytes = 0; - } - } - - if (uncache_bytes > 0) { - VideoCore::g_memory->RasterizerMarkRegionCached(uncache_start_addr, uncache_bytes, false); - } - - cached_pages = {}; -} - RasterizerAccelerated::VertexArrayInfo RasterizerAccelerated::AnalyzeVertexArray( bool is_indexed, u32 stride_alignment) { const auto& regs = Pica::g_state.regs; diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h index c29d08e41..861e1c736 100644 --- a/src/video_core/rasterizer_accelerated.h +++ b/src/video_core/rasterizer_accelerated.h @@ -18,18 +18,13 @@ public: void AddTriangle(const Pica::Shader::OutputVertex& v0, const Pica::Shader::OutputVertex& v1, const Pica::Shader::OutputVertex& v2) override; - - void UpdatePagesCachedCount(PAddr addr, u32 size, int delta) override; void NotifyPicaRegisterChanged(u32 id) override; - void ClearAll(bool flush) override; - - /// Syncs entire status to match PICA registers void SyncEntireState() override; +protected: /// Sync fixed-function pipeline state virtual void SyncFixedState() = 0; -protected: /// Notifies that a fixed function PICA register changed to the video backend virtual void NotifyFixedFunctionPicaRegisterChanged(u32 id) = 0; @@ -137,7 +132,6 @@ protected: VertexArrayInfo AnalyzeVertexArray(bool is_indexed, u32 stride_alignment = 1); protected: - std::array cached_pages{}; std::vector vertex_batch; bool shader_dirty = true; diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 52833b635..d54bcf519 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -12,8 +12,8 @@ #include "common/alignment.h" #include "common/logging/log.h" #include "common/microprofile.h" +#include "core/memory.h" #include "video_core/pica_state.h" -#include "video_core/rasterizer_accelerated.h" #include "video_core/rasterizer_cache/surface_base.h" #include "video_core/rasterizer_cache/surface_params.h" #include "video_core/rasterizer_cache/utils.h" @@ -22,7 +22,7 @@ namespace VideoCore { -inline auto RangeFromInterval(auto& map, SurfaceInterval interval) { +inline auto RangeFromInterval(auto& map, const auto& interval) { return boost::make_iterator_range(map.equal_range(interval)); } @@ -70,9 +70,10 @@ private: using SurfaceRect_Tuple = std::tuple>; using SurfaceSurfaceRect_Tuple = std::tuple>; + using PageMap = boost::icl::interval_map; public: - RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer, TextureRuntime& runtime); + RasterizerCache(Memory::MemorySystem& memory, TextureRuntime& runtime); ~RasterizerCache() = default; /// Get the best surface match (and its match type) for the given flags @@ -124,6 +125,9 @@ public: /// Flush all cached resources tracked by this cache manager void FlushAll(); + /// Clear all cached resources tracked by this cache manager + void ClearAll(bool flush); + private: void DuplicateSurface(const Surface& src_surface, const Surface& dest_surface); @@ -159,23 +163,24 @@ private: /// Remove surface from the cache void UnregisterSurface(const Surface& surface); + /// Increase/decrease the number of surface in pages touching the specified region + void UpdatePagesCachedCount(PAddr addr, u32 size, int delta); + private: - VideoCore::RasterizerAccelerated& rasterizer; + Memory::MemorySystem& memory; TextureRuntime& runtime; SurfaceCache surface_cache; + PageMap cached_pages; SurfaceMap dirty_regions; SurfaceSet remove_surfaces; u16 resolution_scale_factor; std::vector> download_queue; - std::vector staging_buffer; std::unordered_map texture_cube_cache; - std::recursive_mutex mutex; }; template -RasterizerCache::RasterizerCache(VideoCore::RasterizerAccelerated& rasterizer, - TextureRuntime& runtime) - : rasterizer{rasterizer}, runtime{runtime} { +RasterizerCache::RasterizerCache(Memory::MemorySystem& memory_, TextureRuntime& runtime_) + : memory{memory_}, runtime{runtime_} { resolution_scale_factor = VideoCore::GetResolutionScaleFactor(); } @@ -910,7 +915,7 @@ void RasterizerCache::UploadSurface(const Surface& surface, SurfaceInterval i const auto staging = runtime.FindStaging( load_info.width * load_info.height * surface->GetInternalBytesPerPixel(), true); - MemoryRef source_ptr = VideoCore::g_memory->GetPhysicalRef(load_info.addr); + MemoryRef source_ptr = memory.GetPhysicalRef(load_info.addr); if (!source_ptr) [[unlikely]] { return; } @@ -944,7 +949,7 @@ void RasterizerCache::DownloadSurface(const Surface& surface, SurfaceInterval surface->Download(download, staging); - MemoryRef dest_ptr = VideoCore::g_memory->GetPhysicalRef(flush_start); + MemoryRef dest_ptr = memory.GetPhysicalRef(flush_start); if (!dest_ptr) [[unlikely]] { return; } @@ -964,7 +969,7 @@ void RasterizerCache::DownloadFillSurface(const Surface& surface, SurfaceInte const u32 flush_end = boost::icl::last_next(interval); ASSERT(flush_start >= surface->addr && flush_end <= surface->end); - MemoryRef dest_ptr = VideoCore::g_memory->GetPhysicalRef(flush_start); + MemoryRef dest_ptr = memory.GetPhysicalRef(flush_start); if (!dest_ptr) [[unlikely]] { return; } @@ -1062,9 +1067,32 @@ bool RasterizerCache::ValidateByReinterpretation(const Surface& surface, Surf } template -void RasterizerCache::FlushRegion(PAddr addr, u32 size, Surface flush_surface) { - std::lock_guard lock{mutex}; +void RasterizerCache::ClearAll(bool flush) { + const auto flush_interval = PageMap::interval_type::right_open(0x0, 0xFFFFFFFF); + // Force flush all surfaces from the cache + if (flush) { + FlushRegion(0x0, 0xFFFFFFFF); + } + // Unmark all of the marked pages + for (auto& pair : RangeFromInterval(cached_pages, flush_interval)) { + const auto interval = pair.first & flush_interval; + const PAddr interval_start_addr = boost::icl::first(interval) << Memory::CITRA_PAGE_BITS; + const PAddr interval_end_addr = boost::icl::last_next(interval) << Memory::CITRA_PAGE_BITS; + const u32 interval_size = interval_end_addr - interval_start_addr; + + memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false); + } + + // Remove the whole cache without really looking at it. + cached_pages -= flush_interval; + dirty_regions -= SurfaceInterval(0x0, 0xFFFFFFFF); + surface_cache -= SurfaceInterval(0x0, 0xFFFFFFFF); + remove_surfaces.clear(); +} + +template +void RasterizerCache::FlushRegion(PAddr addr, u32 size, Surface flush_surface) { if (size == 0) [[unlikely]] { return; } @@ -1116,8 +1144,6 @@ void RasterizerCache::FlushAll() { template void RasterizerCache::InvalidateRegion(PAddr addr, u32 size, const Surface& region_owner) { - std::lock_guard lock{mutex}; - if (size == 0) [[unlikely]] { return; } @@ -1189,28 +1215,60 @@ auto RasterizerCache::CreateSurface(SurfaceParams& params) -> Surface { template void RasterizerCache::RegisterSurface(const Surface& surface) { - std::lock_guard lock{mutex}; - if (surface->registered) { return; } surface->registered = true; surface_cache.add({surface->GetInterval(), SurfaceSet{surface}}); - rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, 1); + UpdatePagesCachedCount(surface->addr, surface->size, 1); } template void RasterizerCache::UnregisterSurface(const Surface& surface) { - std::lock_guard lock{mutex}; - if (!surface->registered) { return; } surface->registered = false; - rasterizer.UpdatePagesCachedCount(surface->addr, surface->size, -1); + UpdatePagesCachedCount(surface->addr, surface->size, -1); surface_cache.subtract({surface->GetInterval(), SurfaceSet{surface}}); } +template +void RasterizerCache::UpdatePagesCachedCount(PAddr addr, u32 size, int delta) { + const u32 num_pages = + ((addr + size - 1) >> Memory::CITRA_PAGE_BITS) - (addr >> Memory::CITRA_PAGE_BITS) + 1; + const u32 page_start = addr >> Memory::CITRA_PAGE_BITS; + const u32 page_end = page_start + num_pages; + + // Interval maps will erase segments if count reaches 0, so if delta is negative we have to + // subtract after iterating + const auto pages_interval = PageMap::interval_type::right_open(page_start, page_end); + if (delta > 0) { + cached_pages.add({pages_interval, delta}); + } + + for (const auto& pair : RangeFromInterval(cached_pages, pages_interval)) { + const auto interval = pair.first & pages_interval; + const int count = pair.second; + + const PAddr interval_start_addr = boost::icl::first(interval) << Memory::CITRA_PAGE_BITS; + const PAddr interval_end_addr = boost::icl::last_next(interval) << Memory::CITRA_PAGE_BITS; + const u32 interval_size = interval_end_addr - interval_start_addr; + + if (delta > 0 && count == delta) { + memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, true); + } else if (delta < 0 && count == -delta) { + memory.RasterizerMarkRegionCached(interval_start_addr, interval_size, false); + } else { + ASSERT(count >= 0); + } + } + + if (delta < 0) { + cached_pages.add({pages_interval, delta}); + } +} + } // namespace VideoCore diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index df37cb89c..e1dfed021 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -13,7 +13,6 @@ #include "video_core/renderer_opengl/gl_driver.h" #include "video_core/renderer_opengl/gl_rasterizer.h" #include "video_core/renderer_opengl/gl_shader_gen.h" -#include "video_core/renderer_opengl/gl_vars.h" #include "video_core/renderer_opengl/pica_to_gl.h" #include "video_core/renderer_opengl/renderer_opengl.h" #include "video_core/video_core.h" @@ -25,8 +24,9 @@ constexpr std::size_t INDEX_BUFFER_SIZE = 1 * 1024 * 1024; constexpr std::size_t UNIFORM_BUFFER_SIZE = 2 * 1024 * 1024; constexpr std::size_t TEXTURE_BUFFER_SIZE = 1 * 1024 * 1024; -RasterizerOpenGL::RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver) - : driver{driver}, runtime{driver}, res_cache{*this, runtime}, +RasterizerOpenGL::RasterizerOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window, + Driver& driver_) + : memory{memory_}, driver{driver_}, runtime{driver}, res_cache{memory, runtime}, shader_program_manager{emu_window, driver, !driver.IsOpenGLES()}, vertex_buffer{GL_ARRAY_BUFFER, VERTEX_BUFFER_SIZE}, uniform_buffer{GL_UNIFORM_BUFFER, UNIFORM_BUFFER_SIZE}, @@ -210,7 +210,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset, u32 data_size = loader.byte_count * vertex_num; res_cache.FlushRegion(data_addr, data_size, nullptr); - std::memcpy(array_ptr, VideoCore::g_memory->GetPhysicalPointer(data_addr), data_size); + std::memcpy(array_ptr, memory.GetPhysicalPointer(data_addr), data_size); array_ptr += data_size; buffer_offset += data_size; @@ -326,9 +326,9 @@ bool RasterizerOpenGL::AccelerateDrawBatchInternal(bool is_indexed) { return false; } - const u8* index_data = VideoCore::g_memory->GetPhysicalPointer( - regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + - regs.pipeline.index_array.offset); + const u8* index_data = + memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + + regs.pipeline.index_array.offset); std::tie(buffer_ptr, buffer_offset, std::ignore) = index_buffer.Map(index_buffer_size, 4); std::memcpy(buffer_ptr, index_data, index_buffer_size); index_buffer.Unmap(index_buffer_size); @@ -772,6 +772,10 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(PAddr addr, u32 size) { res_cache.InvalidateRegion(addr, size, nullptr); } +void RasterizerOpenGL::ClearAll(bool flush) { + res_cache.ClearAll(flush); +} + MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); bool RasterizerOpenGL::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) { MICROPROFILE_SCOPE(OpenGL_Blits); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 49196acb4..6ff4254af 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -11,6 +11,10 @@ #include "video_core/renderer_opengl/gl_stream_buffer.h" #include "video_core/renderer_opengl/gl_texture_runtime.h" +namespace Memory { +class MemorySystem; +} + namespace Frontend { class EmuWindow; } @@ -24,7 +28,8 @@ class ShaderProgramManager; class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { public: - explicit RasterizerOpenGL(Frontend::EmuWindow& emu_window, Driver& driver); + explicit RasterizerOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window, + Driver& driver); ~RasterizerOpenGL() override; void LoadDiskResources(const std::atomic_bool& stop_loading, @@ -35,6 +40,7 @@ public: void FlushRegion(PAddr addr, u32 size) override; void InvalidateRegion(PAddr addr, u32 size) override; void FlushAndInvalidateRegion(PAddr addr, u32 size) override; + void ClearAll(bool flush) override; bool AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) override; bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override; bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override; @@ -132,6 +138,7 @@ private: bool SetupGeometryShader(); private: + Memory::MemorySystem& memory; Driver& driver; OpenGLState state; TextureRuntime runtime; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index eb209c699..89ad5df76 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -273,10 +273,11 @@ static std::array MakeOrthographicMatrix(const float width, cons return matrix; } -RendererOpenGL::RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window) - : RendererBase{window, secondary_window}, driver{Settings::values.graphics_api.GetValue() == - Settings::GraphicsAPI::OpenGLES, - Settings::values.renderer_debug.GetValue()}, +RendererOpenGL::RendererOpenGL(Memory::MemorySystem& memory_, Frontend::EmuWindow& window, + Frontend::EmuWindow* secondary_window) + : RendererBase{window, secondary_window}, memory{memory_}, + driver{Settings::values.graphics_api.GetValue() == Settings::GraphicsAPI::OpenGLES, + Settings::values.renderer_debug.GetValue()}, frame_dumper(Core::System::GetInstance().VideoDumper(), window) { window.mailbox = std::make_unique(); if (secondary_window) { @@ -294,7 +295,7 @@ VideoCore::ResultStatus RendererOpenGL::Init() { } InitOpenGLObjects(); - rasterizer = std::make_unique(render_window, driver); + rasterizer = std::make_unique(memory, render_window, driver); return VideoCore::ResultStatus::Success; } @@ -495,8 +496,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& fram screen_info.display_texcoords = Common::Rectangle(0.f, 0.f, 1.f, 1.f); Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); - - const u8* framebuffer_data = VideoCore::g_memory->GetPhysicalPointer(framebuffer_addr); + const u8* framebuffer_data = memory.GetPhysicalPointer(framebuffer_addr); state.texture_units[0].texture_2d = screen_info.texture.resource.handle; state.Apply(); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 143e2a1eb..e52d54bf4 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -16,6 +16,10 @@ namespace Layout { struct FramebufferLayout; } +namespace Memory { +class MemorySystem; +} + namespace Frontend { struct Frame { @@ -57,7 +61,8 @@ class RasterizerOpenGL; class RendererOpenGL : public RendererBase { public: - explicit RendererOpenGL(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window); + explicit RendererOpenGL(Memory::MemorySystem& memory, Frontend::EmuWindow& window, + Frontend::EmuWindow* secondary_window); ~RendererOpenGL() override; VideoCore::ResultStatus Init() override; @@ -116,6 +121,7 @@ private: void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); private: + Memory::MemorySystem& memory; Driver driver; OpenGLState state; std::unique_ptr rasterizer; diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2c02794dd..800048bdd 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -100,8 +100,9 @@ std::string BuildCommaSeparatedExtensions(std::vector available_ext } // Anonymous namespace -RendererVulkan::RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window) - : RendererBase{window, secondary_window}, +RendererVulkan::RendererVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& window, + Frontend::EmuWindow* secondary_window) + : RendererBase{window, secondary_window}, memory{memory_}, telemetry_session{Core::System::GetInstance().TelemetrySession()}, instance{window, Settings::values.physical_device.GetValue()}, scheduler{instance, renderpass_cache}, @@ -110,7 +111,8 @@ RendererVulkan::RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* renderpass_cache}, vertex_buffer{instance, scheduler, vk::BufferUsageFlagBits::eVertexBuffer, VERTEX_BUFFER_SIZE}, - rasterizer{render_window, instance, scheduler, desc_manager, runtime, renderpass_cache} { + rasterizer{memory, render_window, instance, scheduler, + desc_manager, runtime, renderpass_cache} { Report(); window.mailbox = std::make_unique(instance, swapchain, renderpass_cache); } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index dd499371d..e57bc77c8 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -23,12 +23,19 @@ namespace Core { class TelemetrySession; } +namespace Memory { +class MemorySystem; +} + namespace Layout { struct FramebufferLayout; } namespace Vulkan { +/** + * Structure used for storing information about the textures for each 3DS screen + **/ struct TextureInfo { u32 width; u32 height; @@ -38,6 +45,9 @@ struct TextureInfo { VmaAllocation allocation; }; +/** + * Structure used for storing information about the display target for each 3DS screen + **/ struct ScreenInfo { TextureInfo texture; Common::Rectangle texcoords; @@ -50,7 +60,8 @@ class RendererVulkan : public RendererBase { static constexpr std::size_t PRESENT_PIPELINES = 3; public: - explicit RendererVulkan(Frontend::EmuWindow& window, Frontend::EmuWindow* secondary_window); + explicit RendererVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& window, + Frontend::EmuWindow* secondary_window); ~RendererVulkan() override; VideoCore::ResultStatus Init() override; @@ -111,6 +122,7 @@ private: void LoadColorToActiveVkTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); private: + Memory::MemorySystem& memory; Core::TelemetrySession& telemetry_session; Instance instance; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index cbdd5c493..db9aa32e6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -57,11 +57,12 @@ struct DrawParams { return std::min(max_size, TEXTURE_BUFFER_SIZE); } -RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instance& instance, - Scheduler& scheduler, DescriptorManager& desc_manager, - TextureRuntime& runtime, RenderpassCache& renderpass_cache) - : instance{instance}, scheduler{scheduler}, runtime{runtime}, - renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{*this, runtime}, +RasterizerVulkan::RasterizerVulkan(Memory::MemorySystem& memory_, Frontend::EmuWindow& emu_window, + const Instance& instance, Scheduler& scheduler, + DescriptorManager& desc_manager, TextureRuntime& runtime, + RenderpassCache& renderpass_cache) + : memory{memory_}, instance{instance}, scheduler{scheduler}, runtime{runtime}, + renderpass_cache{renderpass_cache}, desc_manager{desc_manager}, res_cache{memory, runtime}, pipeline_cache{instance, scheduler, renderpass_cache, desc_manager}, null_surface{NULL_PARAMS, vk::Format::eR8G8B8A8Unorm, NULL_USAGE, vk::ImageAspectFlagBits::eColor, runtime}, @@ -235,7 +236,7 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi const u32 data_size = loader.byte_count * vertex_num; res_cache.FlushRegion(data_addr, data_size); - const u8* src_ptr = VideoCore::g_memory->GetPhysicalPointer(data_addr); + const u8* src_ptr = memory.GetPhysicalPointer(data_addr); u8* dst_ptr = array_ptr + buffer_offset; // Align stride up if required by Vulkan implementation. @@ -270,6 +271,9 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi // Bind the generated bindings scheduler.Record([this, binding_count = layout.binding_count, vertex_offsets = binding_offsets](vk::CommandBuffer cmdbuf) { + for (auto& offset : vertex_offsets) { + ASSERT_MSG(offset != 0x8000000, "Bad offset"); + } cmdbuf.bindVertexBuffers(0, binding_count, vertex_buffers.data(), vertex_offsets.data()); }); } @@ -425,9 +429,9 @@ void RasterizerVulkan::SetupIndexArray() { const vk::IndexType index_type = native_u8 ? vk::IndexType::eUint8EXT : vk::IndexType::eUint16; const u32 index_buffer_size = regs.pipeline.num_vertices * (native_u8 ? 1 : 2); - const u8* index_data = VideoCore::g_memory->GetPhysicalPointer( - regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + - regs.pipeline.index_array.offset); + const u8* index_data = + memory.GetPhysicalPointer(regs.pipeline.vertex_attributes.GetPhysicalBaseAddress() + + regs.pipeline.index_array.offset); auto [index_ptr, index_offset, _] = stream_buffer.Map(index_buffer_size, 2); if (index_u8 && !native_u8) { @@ -852,6 +856,10 @@ void RasterizerVulkan::FlushAndInvalidateRegion(PAddr addr, u32 size) { res_cache.InvalidateRegion(addr, size, nullptr); } +void RasterizerVulkan::ClearAll(bool flush) { + res_cache.ClearAll(flush); +} + MICROPROFILE_DEFINE(Vulkan_Blits, "Vulkan", "Blits", MP_RGB(100, 100, 255)); bool RasterizerVulkan::AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) { MICROPROFILE_SCOPE(Vulkan_Blits); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index c70d2d3a7..a6a2f05f5 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -15,6 +15,10 @@ namespace Frontend { class EmuWindow; } +namespace Memory { +class MemorySystem; +} + namespace Vulkan { struct ScreenInfo; @@ -58,9 +62,10 @@ class RasterizerVulkan : public VideoCore::RasterizerAccelerated { friend class RendererVulkan; public: - explicit RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instance& instance, - Scheduler& scheduler, DescriptorManager& desc_manager, - TextureRuntime& runtime, RenderpassCache& renderpass_cache); + explicit RasterizerVulkan(Memory::MemorySystem& memory, Frontend::EmuWindow& emu_window, + const Instance& instance, Scheduler& scheduler, + DescriptorManager& desc_manager, TextureRuntime& runtime, + RenderpassCache& renderpass_cache); ~RasterizerVulkan() override; void LoadDiskResources(const std::atomic_bool& stop_loading, @@ -71,6 +76,7 @@ public: void FlushRegion(PAddr addr, u32 size) override; void InvalidateRegion(PAddr addr, u32 size) override; void FlushAndInvalidateRegion(PAddr addr, u32 size) override; + void ClearAll(bool flush) override; bool AccelerateDisplayTransfer(const GPU::Regs::DisplayTransferConfig& config) override; bool AccelerateTextureCopy(const GPU::Regs::DisplayTransferConfig& config) override; bool AccelerateFill(const GPU::Regs::MemoryFillConfig& config) override; @@ -151,6 +157,7 @@ private: vk::Sampler CreateSampler(const SamplerInfo& info); private: + Memory::MemorySystem& memory; const Instance& instance; Scheduler& scheduler; TextureRuntime& runtime; diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index ea13d81c6..781ea6133 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -40,10 +40,10 @@ ResultStatus Init(Frontend::EmuWindow& emu_window, Frontend::EmuWindow* secondar case Settings::GraphicsAPI::OpenGL: case Settings::GraphicsAPI::OpenGLES: OpenGL::GLES = graphics_api == Settings::GraphicsAPI::OpenGLES; - g_renderer = std::make_unique(emu_window, secondary_window); + g_renderer = std::make_unique(memory, emu_window, secondary_window); break; case Settings::GraphicsAPI::Vulkan: - g_renderer = std::make_unique(emu_window, secondary_window); + g_renderer = std::make_unique(memory, emu_window, secondary_window); break; default: LOG_CRITICAL(Render, "Invalid graphics API enum value {}", graphics_api);