From bfe45774f16e958bf34ed0d58a1d31e2325df47d Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 Mar 2018 21:04:30 -0400 Subject: video_core: Move FramebufferInfo to FramebufferConfig in GPU. --- src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 94530724e..7cd1d9306 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -26,14 +26,14 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 "Drawing from address %lx offset %08X Width %u Height %u Stride %u Format %u", addr, offset, width, height, stride, format); - using PixelFormat = RendererBase::FramebufferInfo::PixelFormat; + using PixelFormat = Tegra::FramebufferConfig::PixelFormat; using Flags = NVFlinger::BufferQueue::BufferTransformFlags; const bool flip_vertical = static_cast(transform) & static_cast(Flags::FlipV); - const RendererBase::FramebufferInfo framebuffer_info{ + const Tegra::FramebufferConfig framebuffer{ addr, offset, width, height, stride, static_cast(format), flip_vertical}; Core::System::GetInstance().perf_stats.EndGameFrame(); - VideoCore::g_renderer->SwapBuffers(framebuffer_info); + VideoCore::g_renderer->SwapBuffers(framebuffer); } } // namespace Devices -- cgit v1.2.3 From 63d3924b5bb5dd17f1de9dfe3a357df293fc113d Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 Mar 2018 22:56:41 -0400 Subject: memory: Port RasterizerFlushVirtualRegion from Citra. --- src/core/memory.cpp | 39 +++++++++++++++++++++++++++++++++++++++ src/core/memory.h | 20 +++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'src/core') diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 4e34d8334..8a83de904 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -42,6 +42,9 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa LOG_DEBUG(HW_Memory, "Mapping %p onto %016" PRIX64 "-%016" PRIX64, memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); + RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE, + FlushMode::FlushAndInvalidate); + VAddr end = base + size; while (base != end) { ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at %016" PRIX64, base); @@ -293,6 +296,42 @@ u8* GetPhysicalPointer(PAddr address) { return target_pointer; } +void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { + // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be + // null here + if (VideoCore::g_renderer == nullptr) { + return; + } + + VAddr end = start + size; + + auto CheckRegion = [&](VAddr region_start, VAddr region_end) { + if (start >= region_end || end <= region_start) { + // No overlap with region + return; + } + + VAddr overlap_start = std::max(start, region_start); + VAddr overlap_end = std::min(end, region_end); + u32 overlap_size = overlap_end - overlap_start; + + auto* rasterizer = VideoCore::g_renderer->Rasterizer(); + switch (mode) { + case FlushMode::Flush: + rasterizer->FlushRegion(region_start, overlap_size); + break; + case FlushMode::Invalidate: + rasterizer->InvalidateRegion(region_start, overlap_size); + break; + case FlushMode::FlushAndInvalidate: + rasterizer->FlushAndInvalidateRegion(region_start, overlap_size); + break; + } + }; + + CheckRegion(HEAP_VADDR, HEAP_VADDR_END); +} + u8 Read8(const VAddr addr) { return Read(addr); } diff --git a/src/core/memory.h b/src/core/memory.h index f406cc848..1c7232115 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -36,7 +36,10 @@ enum class PageType : u8 { Unmapped, /// Page is mapped to regular memory. This is the only type you can get pointers to. Memory, - /// Page is mapped to a memory hook, which intercepts read and write requests. + /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and + /// invalidation + RasterizerCachedMemory, + /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. Special, }; @@ -253,4 +256,19 @@ boost::optional PhysicalToVirtualAddress(PAddr addr); */ u8* GetPhysicalPointer(PAddr address); +enum class FlushMode { + /// Write back modified surfaces to RAM + Flush, + /// Remove region from the cache + Invalidate, + /// Write back modified surfaces to RAM, and also remove them from the cache + FlushAndInvalidate, +}; + +/** + * Flushes and invalidates any externally cached rasterizer resources touching the given virtual + * address region. + */ +void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); + } // namespace Memory -- cgit v1.2.3 From e12c2cf8c692bf7581dda96c601e30c2a969086c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 22 Mar 2018 23:18:04 -0400 Subject: nvdisp_disp0: Always flush and invalidate framebuffer region. - Workaround for texture forwarding until we have a better place. --- src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 7cd1d9306..db030a8e2 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -33,6 +33,13 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 addr, offset, width, height, stride, static_cast(format), flip_vertical}; Core::System::GetInstance().perf_stats.EndGameFrame(); + + // TODO(bunnei): The framebuffer region should only be flushed and invalidated if it is written + // to, not every frame. When we find the right place for this, the below line can be removed. + Memory::RasterizerFlushVirtualRegion(framebuffer.address, + framebuffer.width * framebuffer.height * 4, + Memory::FlushMode::FlushAndInvalidate); + VideoCore::g_renderer->SwapBuffers(framebuffer); } -- cgit v1.2.3 From ec4e1a3685d458147ac76f4cf53ea86632d0debd Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 14:58:27 -0400 Subject: renderer_opengl: Better handling of framebuffer transform flags. --- src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 4 +--- src/core/hle/service/nvflinger/buffer_queue.h | 2 ++ src/video_core/gpu.h | 5 ++++- src/video_core/renderer_opengl/renderer_opengl.cpp | 18 ++++++++++++++++-- 4 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index db030a8e2..f6c2b24a8 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -27,10 +27,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 offset, width, height, stride, format); using PixelFormat = Tegra::FramebufferConfig::PixelFormat; - using Flags = NVFlinger::BufferQueue::BufferTransformFlags; - const bool flip_vertical = static_cast(transform) & static_cast(Flags::FlipV); const Tegra::FramebufferConfig framebuffer{ - addr, offset, width, height, stride, static_cast(format), flip_vertical}; + addr, offset, width, height, stride, static_cast(format), transform}; Core::System::GetInstance().perf_stats.EndGameFrame(); diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 686eadca7..1de5767cb 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -47,6 +47,8 @@ public: ~BufferQueue() = default; enum class BufferTransformFlags : u32 { + /// No transform flags are set + Unset = 0x00, /// Flip source image horizontally (around the vertical axis) FlipH = 0x01, /// Flip source image vertically (around the horizontal axis) diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index f3c5e366a..206b3e05e 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -8,6 +8,7 @@ #include #include #include "common/common_types.h" +#include "core/hle/service/nvflinger/buffer_queue.h" #include "video_core/memory_manager.h" namespace Tegra { @@ -38,7 +39,9 @@ struct FramebufferConfig { u32 height; u32 stride; PixelFormat pixel_format; - bool flip_vertical; + + using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; + TransformFlags transform_flags; }; namespace Engines { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 047389fee..ef63cbcf0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -141,6 +141,9 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf const u32 size_in_bytes{framebuffer.stride * framebuffer.height * bpp}; const VAddr framebuffer_addr{framebuffer.address}; + // Framebuffer orientation handling + framebuffer_transform_flags = framebuffer.transform_flags; + // Ensure no bad interactions with GL_UNPACK_ALIGNMENT, which by default // only allows rows to have a memory alignement of 4. ASSERT(framebuffer.stride % 4 == 0); @@ -292,8 +295,19 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h) { const auto& texcoords = screen_info.display_texcoords; - const auto& left = framebuffer_flip_vertical ? texcoords.right : texcoords.left; - const auto& right = framebuffer_flip_vertical ? texcoords.left : texcoords.right; + auto left = texcoords.left; + auto right = texcoords.right; + if (framebuffer_transform_flags != Tegra::FramebufferConfig::TransformFlags::Unset) + if (framebuffer_transform_flags == Tegra::FramebufferConfig::TransformFlags::FlipV) { + // Flip the framebuffer vertically + left = texcoords.right; + right = texcoords.left; + } else { + // Other transformations are unsupported + LOG_CRITICAL(HW_GPU, "unsupported framebuffer_transform_flags=%d", + framebuffer_transform_flags); + UNIMPLEMENTED(); + } std::array vertices = {{ ScreenRectVertex(x, y, texcoords.top, right), -- cgit v1.2.3 From 11047d7fd511fd9ae6130da7bc824fefa6fb64c1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:01:45 -0400 Subject: rasterizer: Flush and invalidate regions should be 64-bit. --- src/core/memory.cpp | 4 ++-- src/core/memory.h | 2 +- src/video_core/rasterizer_interface.h | 6 +++--- src/video_core/renderer_opengl/gl_rasterizer.cpp | 6 +++--- src/video_core/renderer_opengl/gl_rasterizer.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8a83de904..d8aab7090 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -296,7 +296,7 @@ u8* GetPhysicalPointer(PAddr address) { return target_pointer; } -void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { +void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be // null here if (VideoCore::g_renderer == nullptr) { @@ -313,7 +313,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode) { VAddr overlap_start = std::max(start, region_start); VAddr overlap_end = std::min(end, region_end); - u32 overlap_size = overlap_end - overlap_start; + u64 overlap_size = overlap_end - overlap_start; auto* rasterizer = VideoCore::g_renderer->Rasterizer(); switch (mode) { diff --git a/src/core/memory.h b/src/core/memory.h index 1c7232115..3e2c3f23d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -269,6 +269,6 @@ enum class FlushMode { * Flushes and invalidates any externally cached rasterizer resources touching the given virtual * address region. */ -void RasterizerFlushVirtualRegion(VAddr start, u32 size, FlushMode mode); +void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode); } // namespace Memory diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 6514d7ded..a493e1d60 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -25,14 +25,14 @@ public: virtual void FlushAll() = 0; /// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory - virtual void FlushRegion(VAddr addr, u32 size) = 0; + virtual void FlushRegion(VAddr addr, u64 size) = 0; /// Notify rasterizer that any caches of the specified region should be invalidated - virtual void InvalidateRegion(VAddr addr, u32 size) = 0; + virtual void InvalidateRegion(VAddr addr, u64 size) = 0; /// Notify rasterizer that any caches of the specified region should be flushed to 3DS memory /// and invalidated - virtual void FlushAndInvalidateRegion(VAddr addr, u32 size) = 0; + virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; /// Attempt to use a faster method to perform a display transfer with is_texture_copy = 0 virtual bool AccelerateDisplayTransfer(const void* config) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b51614c25..09828e48d 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -194,17 +194,17 @@ void RasterizerOpenGL::FlushAll() { res_cache.FlushAll(); } -void RasterizerOpenGL::FlushRegion(VAddr addr, u32 size) { +void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) { MICROPROFILE_SCOPE(OpenGL_CacheManagement); res_cache.FlushRegion(addr, size); } -void RasterizerOpenGL::InvalidateRegion(VAddr addr, u32 size) { +void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size) { MICROPROFILE_SCOPE(OpenGL_CacheManagement); res_cache.InvalidateRegion(addr, size, nullptr); } -void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u32 size) { +void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { MICROPROFILE_SCOPE(OpenGL_CacheManagement); res_cache.FlushRegion(addr, size); res_cache.InvalidateRegion(addr, size, nullptr); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index f5c7b1162..b387f383b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -32,9 +32,9 @@ public: void DrawTriangles() override; void NotifyMaxwellRegisterChanged(u32 id) override; void FlushAll() override; - void FlushRegion(VAddr addr, u32 size) override; - void InvalidateRegion(VAddr addr, u32 size) override; - void FlushAndInvalidateRegion(VAddr addr, u32 size) override; + void FlushRegion(VAddr addr, u64 size) override; + void InvalidateRegion(VAddr addr, u64 size) override; + void FlushAndInvalidateRegion(VAddr addr, u64 size) override; bool AccelerateDisplayTransfer(const void* config) override; bool AccelerateTextureCopy(const void* config) override; bool AccelerateFill(const void* config) override; -- cgit v1.2.3 From 1a158dfcd660058d2f87cb6eb4662861db203386 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:10:02 -0400 Subject: memory: RasterizerFlushVirtualRegion should also check process image region. --- src/core/memory.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/core') diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d8aab7090..fd5a57022 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -329,6 +329,7 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { } }; + CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END); CheckRegion(HEAP_VADDR, HEAP_VADDR_END); } -- cgit v1.2.3 From b5f3e7951b69fe689408f4560c83860302c540e5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:46:21 -0400 Subject: memory: Fix typo in RasterizerFlushVirtualRegion. --- src/core/memory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/memory.cpp b/src/core/memory.cpp index fd5a57022..0eca4e76e 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -318,13 +318,13 @@ void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { auto* rasterizer = VideoCore::g_renderer->Rasterizer(); switch (mode) { case FlushMode::Flush: - rasterizer->FlushRegion(region_start, overlap_size); + rasterizer->FlushRegion(overlap_start, overlap_size); break; case FlushMode::Invalidate: - rasterizer->InvalidateRegion(region_start, overlap_size); + rasterizer->InvalidateRegion(overlap_start, overlap_size); break; case FlushMode::FlushAndInvalidate: - rasterizer->FlushAndInvalidateRegion(region_start, overlap_size); + rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size); break; } }; -- cgit v1.2.3 From 054393917e99d307eea0aabc78c0c6e5e709b2c7 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 23 Mar 2018 15:49:04 -0400 Subject: renderer_opengl: Fixes for properly flushing & rendering the framebuffer. --- src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 6 ------ src/video_core/renderer_opengl/renderer_opengl.cpp | 18 ++++++++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index f6c2b24a8..87b3a2d74 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -32,12 +32,6 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 Core::System::GetInstance().perf_stats.EndGameFrame(); - // TODO(bunnei): The framebuffer region should only be flushed and invalidated if it is written - // to, not every frame. When we find the right place for this, the below line can be removed. - Memory::RasterizerFlushVirtualRegion(framebuffer.address, - framebuffer.width * framebuffer.height * 4, - Memory::FlushMode::FlushAndInvalidate); - VideoCore::g_renderer->SwapBuffers(framebuffer); } diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index ef63cbcf0..4628f6db0 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -137,9 +137,15 @@ void RendererOpenGL::SwapBuffers(boost::optional(0.f, 0.f, 1.f, 1.f); - Rasterizer()->FlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height); + Rasterizer()->FlushRegion(framebuffer_addr, size_in_bytes); - VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bpp, 4, - Memory::GetPointer(framebuffer.address), + VideoCore::MortonCopyPixels128(framebuffer.width, framebuffer.height, bytes_per_pixel, 4, + Memory::GetPointer(framebuffer_addr), gl_framebuffer_data.data(), true); state.texture_units[0].texture_2d = screen_info.texture.resource.handle; -- cgit v1.2.3