summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp11
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h2
-rw-r--r--src/core/memory.cpp40
-rw-r--r--src/core/memory.h20
4 files changed, 66 insertions, 7 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 94530724e..87b3a2d74 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -26,14 +26,13 @@ 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 Flags = NVFlinger::BufferQueue::BufferTransformFlags;
- const bool flip_vertical = static_cast<u32>(transform) & static_cast<u32>(Flags::FlipV);
- const RendererBase::FramebufferInfo framebuffer_info{
- addr, offset, width, height, stride, static_cast<PixelFormat>(format), flip_vertical};
+ using PixelFormat = Tegra::FramebufferConfig::PixelFormat;
+ const Tegra::FramebufferConfig framebuffer{
+ addr, offset, width, height, stride, static_cast<PixelFormat>(format), transform};
Core::System::GetInstance().perf_stats.EndGameFrame();
- VideoCore::g_renderer->SwapBuffers(framebuffer_info);
+
+ VideoCore::g_renderer->SwapBuffers(framebuffer);
}
} // namespace Devices
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/core/memory.cpp b/src/core/memory.cpp
index a9beccb95..d6469dd3d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -41,6 +41,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);
@@ -288,6 +291,43 @@ u8* GetPhysicalPointer(PAddr address) {
return target_pointer;
}
+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) {
+ 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);
+ u64 overlap_size = overlap_end - overlap_start;
+
+ auto* rasterizer = VideoCore::g_renderer->Rasterizer();
+ switch (mode) {
+ case FlushMode::Flush:
+ rasterizer->FlushRegion(overlap_start, overlap_size);
+ break;
+ case FlushMode::Invalidate:
+ rasterizer->InvalidateRegion(overlap_start, overlap_size);
+ break;
+ case FlushMode::FlushAndInvalidate:
+ rasterizer->FlushAndInvalidateRegion(overlap_start, overlap_size);
+ break;
+ }
+ };
+
+ CheckRegion(PROCESS_IMAGE_VADDR, PROCESS_IMAGE_VADDR_END);
+ CheckRegion(HEAP_VADDR, HEAP_VADDR_END);
+}
+
u8 Read8(const VAddr addr) {
return Read<u8>(addr);
}
diff --git a/src/core/memory.h b/src/core/memory.h
index f5bf0141f..4b9c482fe 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,
};
@@ -242,4 +245,19 @@ boost::optional<VAddr> 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, u64 size, FlushMode mode);
+
} // namespace Memory