aboutsummaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/buffer_cache/buffer_base.h2
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h49
-rw-r--r--src/video_core/memory_manager.cpp4
-rw-r--r--src/video_core/query_cache.h12
-rw-r--r--src/video_core/rasterizer_accelerated.cpp17
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp19
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp18
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp5
-rw-r--r--src/video_core/shader_cache.cpp12
-rw-r--r--src/video_core/shader_cache.h4
-rw-r--r--src/video_core/texture_cache/texture_cache.h12
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h10
-rw-r--r--src/video_core/textures/decoders.cpp60
-rw-r--r--src/video_core/textures/decoders.h3
16 files changed, 147 insertions, 91 deletions
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h
index 3e20608ca..0b2bc67b1 100644
--- a/src/video_core/buffer_cache/buffer_base.h
+++ b/src/video_core/buffer_cache/buffer_base.h
@@ -36,7 +36,7 @@ struct NullBufferParams {};
template <class RasterizerInterface>
class BufferBase {
static constexpr u64 PAGES_PER_WORD = 64;
- static constexpr u64 BYTES_PER_PAGE = Core::Memory::PAGE_SIZE;
+ static constexpr u64 BYTES_PER_PAGE = Core::Memory::YUZU_PAGESIZE;
static constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE;
/// Vector tracking modified pages tightly packed with small vector optimization
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index b74ad7900..f015dae56 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -60,8 +60,8 @@ class BufferCache {
// Page size for caching purposes.
// This is unrelated to the CPU page size and it can be changed as it seems optimal.
- static constexpr u32 PAGE_BITS = 16;
- static constexpr u64 PAGE_SIZE = u64{1} << PAGE_BITS;
+ static constexpr u32 YUZU_PAGEBITS = 16;
+ static constexpr u64 YUZU_PAGESIZE = u64{1} << YUZU_PAGEBITS;
static constexpr bool IS_OPENGL = P::IS_OPENGL;
static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS =
@@ -216,8 +216,8 @@ private:
template <typename Func>
void ForEachBufferInRange(VAddr cpu_addr, u64 size, Func&& func) {
- const u64 page_end = Common::DivCeil(cpu_addr + size, PAGE_SIZE);
- for (u64 page = cpu_addr >> PAGE_BITS; page < page_end;) {
+ const u64 page_end = Common::DivCeil(cpu_addr + size, YUZU_PAGESIZE);
+ for (u64 page = cpu_addr >> YUZU_PAGEBITS; page < page_end;) {
const BufferId buffer_id = page_table[page];
if (!buffer_id) {
++page;
@@ -227,7 +227,7 @@ private:
func(buffer_id, buffer);
const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes();
- page = Common::DivCeil(end_addr, PAGE_SIZE);
+ page = Common::DivCeil(end_addr, YUZU_PAGESIZE);
}
}
@@ -262,8 +262,8 @@ private:
}
static bool IsRangeGranular(VAddr cpu_addr, size_t size) {
- return (cpu_addr & ~Core::Memory::PAGE_MASK) ==
- ((cpu_addr + size) & ~Core::Memory::PAGE_MASK);
+ return (cpu_addr & ~Core::Memory::YUZU_PAGEMASK) ==
+ ((cpu_addr + size) & ~Core::Memory::YUZU_PAGEMASK);
}
void RunGarbageCollector();
@@ -439,7 +439,7 @@ private:
u64 minimum_memory = 0;
u64 critical_memory = 0;
- std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table;
+ std::array<BufferId, ((1ULL << 39) >> YUZU_PAGEBITS)> page_table;
};
template <class P>
@@ -926,8 +926,8 @@ void BufferCache<P>::PopAsyncFlushes() {}
template <class P>
bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
- const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
- for (u64 page = addr >> PAGE_BITS; page < page_end;) {
+ const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
+ for (u64 page = addr >> YUZU_PAGEBITS; page < page_end;) {
const BufferId image_id = page_table[page];
if (!image_id) {
++page;
@@ -938,7 +938,7 @@ bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
return true;
}
const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes();
- page = Common::DivCeil(end_addr, PAGE_SIZE);
+ page = Common::DivCeil(end_addr, YUZU_PAGESIZE);
}
return false;
}
@@ -946,8 +946,8 @@ bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
template <class P>
bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) {
const VAddr end_addr = addr + size;
- const u64 page_end = Common::DivCeil(end_addr, PAGE_SIZE);
- for (u64 page = addr >> PAGE_BITS; page < page_end;) {
+ const u64 page_end = Common::DivCeil(end_addr, YUZU_PAGESIZE);
+ for (u64 page = addr >> YUZU_PAGEBITS; page < page_end;) {
const BufferId buffer_id = page_table[page];
if (!buffer_id) {
++page;
@@ -959,15 +959,15 @@ bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) {
if (buf_start_addr < end_addr && addr < buf_end_addr) {
return true;
}
- page = Common::DivCeil(end_addr, PAGE_SIZE);
+ page = Common::DivCeil(end_addr, YUZU_PAGESIZE);
}
return false;
}
template <class P>
bool BufferCache<P>::IsRegionCpuModified(VAddr addr, size_t size) {
- const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
- for (u64 page = addr >> PAGE_BITS; page < page_end;) {
+ const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
+ for (u64 page = addr >> YUZU_PAGEBITS; page < page_end;) {
const BufferId image_id = page_table[page];
if (!image_id) {
++page;
@@ -978,7 +978,7 @@ bool BufferCache<P>::IsRegionCpuModified(VAddr addr, size_t size) {
return true;
}
const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes();
- page = Common::DivCeil(end_addr, PAGE_SIZE);
+ page = Common::DivCeil(end_addr, YUZU_PAGESIZE);
}
return false;
}
@@ -1472,7 +1472,7 @@ BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) {
if (cpu_addr == 0) {
return NULL_BUFFER_ID;
}
- const u64 page = cpu_addr >> PAGE_BITS;
+ const u64 page = cpu_addr >> YUZU_PAGEBITS;
const BufferId buffer_id = page_table[page];
if (!buffer_id) {
return CreateBuffer(cpu_addr, size);
@@ -1493,8 +1493,9 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
VAddr end = cpu_addr + wanted_size;
int stream_score = 0;
bool has_stream_leap = false;
- for (; cpu_addr >> PAGE_BITS < Common::DivCeil(end, PAGE_SIZE); cpu_addr += PAGE_SIZE) {
- const BufferId overlap_id = page_table[cpu_addr >> PAGE_BITS];
+ for (; cpu_addr >> YUZU_PAGEBITS < Common::DivCeil(end, YUZU_PAGESIZE);
+ cpu_addr += YUZU_PAGESIZE) {
+ const BufferId overlap_id = page_table[cpu_addr >> YUZU_PAGEBITS];
if (!overlap_id) {
continue;
}
@@ -1520,11 +1521,11 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
// as a stream buffer. Increase the size to skip constantly recreating buffers.
has_stream_leap = true;
if (expands_right) {
- begin -= PAGE_SIZE * 256;
+ begin -= YUZU_PAGESIZE * 256;
cpu_addr = begin;
}
if (expands_left) {
- end += PAGE_SIZE * 256;
+ end += YUZU_PAGESIZE * 256;
}
}
}
@@ -1598,8 +1599,8 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
}
const VAddr cpu_addr_begin = buffer.CpuAddr();
const VAddr cpu_addr_end = cpu_addr_begin + size;
- const u64 page_begin = cpu_addr_begin / PAGE_SIZE;
- const u64 page_end = Common::DivCeil(cpu_addr_end, PAGE_SIZE);
+ const u64 page_begin = cpu_addr_begin / YUZU_PAGESIZE;
+ const u64 page_end = Common::DivCeil(cpu_addr_end, YUZU_PAGESIZE);
for (u64 page = page_begin; page != page_end; ++page) {
if constexpr (insert) {
page_table[page] = buffer_id;
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index d373be0ba..bf9eb735d 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -369,8 +369,8 @@ bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
if (!cpu_addr) {
return false;
}
- const std::size_t page{(*cpu_addr & Core::Memory::PAGE_MASK) + size};
- return page <= Core::Memory::PAGE_SIZE;
+ const std::size_t page{(*cpu_addr & Core::Memory::YUZU_PAGEMASK) + size};
+ return page <= Core::Memory::YUZU_PAGESIZE;
}
bool MemoryManager::IsContinousRange(GPUVAddr gpu_addr, std::size_t size) const {
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index fcce87acb..889b606b3 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -214,8 +214,8 @@ private:
return cache_begin < addr_end && addr_begin < cache_end;
};
- const u64 page_end = addr_end >> PAGE_BITS;
- for (u64 page = addr_begin >> PAGE_BITS; page <= page_end; ++page) {
+ const u64 page_end = addr_end >> YUZU_PAGEBITS;
+ for (u64 page = addr_begin >> YUZU_PAGEBITS; page <= page_end; ++page) {
const auto& it = cached_queries.find(page);
if (it == std::end(cached_queries)) {
continue;
@@ -235,14 +235,14 @@ private:
/// Registers the passed parameters as cached and returns a pointer to the stored cached query.
CachedQuery* Register(VideoCore::QueryType type, VAddr cpu_addr, u8* host_ptr, bool timestamp) {
rasterizer.UpdatePagesCachedCount(cpu_addr, CachedQuery::SizeInBytes(timestamp), 1);
- const u64 page = static_cast<u64>(cpu_addr) >> PAGE_BITS;
+ const u64 page = static_cast<u64>(cpu_addr) >> YUZU_PAGEBITS;
return &cached_queries[page].emplace_back(static_cast<QueryCache&>(*this), type, cpu_addr,
host_ptr);
}
/// Tries to a get a cached query. Returns nullptr on failure.
CachedQuery* TryGet(VAddr addr) {
- const u64 page = static_cast<u64>(addr) >> PAGE_BITS;
+ const u64 page = static_cast<u64>(addr) >> YUZU_PAGEBITS;
const auto it = cached_queries.find(page);
if (it == std::end(cached_queries)) {
return nullptr;
@@ -260,8 +260,8 @@ private:
uncommitted_flushes->push_back(addr);
}
- static constexpr std::uintptr_t PAGE_SIZE = 4096;
- static constexpr unsigned PAGE_BITS = 12;
+ static constexpr std::uintptr_t YUZU_PAGESIZE = 4096;
+ static constexpr unsigned YUZU_PAGEBITS = 12;
VideoCore::RasterizerInterface& rasterizer;
Tegra::Engines::Maxwell3D& maxwell3d;
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
index 87a29e144..4a197d65d 100644
--- a/src/video_core/rasterizer_accelerated.cpp
+++ b/src/video_core/rasterizer_accelerated.cpp
@@ -24,8 +24,8 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
u64 cache_bytes = 0;
std::atomic_thread_fence(std::memory_order_acquire);
- const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
- for (u64 page = addr >> PAGE_BITS; page != page_end; ++page) {
+ const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
+ for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page);
if (delta > 0) {
@@ -44,26 +44,27 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
if (uncache_bytes == 0) {
uncache_begin = page;
}
- uncache_bytes += PAGE_SIZE;
+ uncache_bytes += YUZU_PAGESIZE;
} else if (uncache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(uncache_begin << PAGE_BITS, uncache_bytes, false);
+ cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes,
+ false);
uncache_bytes = 0;
}
if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
if (cache_bytes == 0) {
cache_begin = page;
}
- cache_bytes += PAGE_SIZE;
+ cache_bytes += YUZU_PAGESIZE;
} else if (cache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(cache_begin << PAGE_BITS, cache_bytes, true);
+ cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
cache_bytes = 0;
}
}
if (uncache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(uncache_begin << PAGE_BITS, uncache_bytes, false);
+ cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false);
}
if (cache_bytes > 0) {
- cpu_memory.RasterizerMarkRegionCached(cache_begin << PAGE_BITS, cache_bytes, true);
+ cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
}
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 01028cee0..34f3f7a67 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -478,13 +478,16 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
}
}
- ASSERT_MSG(framebuffer_crop_rect.top == 0, "Unimplemented");
ASSERT_MSG(framebuffer_crop_rect.left == 0, "Unimplemented");
+ f32 left_start{};
+ if (framebuffer_crop_rect.Top() > 0) {
+ left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
+ static_cast<f32>(framebuffer_crop_rect.Bottom());
+ }
f32 scale_u = static_cast<f32>(framebuffer_width) / static_cast<f32>(screen_info.texture.width);
f32 scale_v =
static_cast<f32>(framebuffer_height) / static_cast<f32>(screen_info.texture.height);
-
// Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
// (e.g. handheld mode) on a 1920x1080 framebuffer.
if (framebuffer_crop_rect.GetWidth() > 0) {
@@ -503,10 +506,14 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
const auto& screen = layout.screen;
const std::array vertices = {
- ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u, left * scale_v),
- ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u, left * scale_v),
- ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u, right * scale_v),
- ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u, right * scale_v),
+ ScreenRectVertex(screen.left, screen.top, texcoords.top * scale_u,
+ left_start + left * scale_v),
+ ScreenRectVertex(screen.right, screen.top, texcoords.bottom * scale_u,
+ left_start + left * scale_v),
+ ScreenRectVertex(screen.left, screen.bottom, texcoords.top * scale_u,
+ left_start + right * scale_v),
+ ScreenRectVertex(screen.right, screen.bottom, texcoords.bottom * scale_u,
+ left_start + right * scale_v),
};
glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 7d1431b6d..bdb71dc53 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -172,7 +172,7 @@ struct FormatTuple {
{VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT
{VK_FORMAT_R8G8_UINT, Attachable | Storage}, // R8G8_UINT
{VK_FORMAT_R32G32_UINT, Attachable | Storage}, // R32G32_UINT
- {VK_FORMAT_UNDEFINED}, // R16G16B16X16_FLOAT
+ {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // R16G16B16X16_FLOAT
{VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT
{VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT
{VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 27e6ebf94..444c29f68 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -1402,12 +1402,15 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
break;
}
- UNIMPLEMENTED_IF(framebuffer_crop_rect.top != 0);
UNIMPLEMENTED_IF(framebuffer_crop_rect.left != 0);
+ f32 left_start{};
+ if (framebuffer_crop_rect.Top() > 0) {
+ left_start = static_cast<f32>(framebuffer_crop_rect.Top()) /
+ static_cast<f32>(framebuffer_crop_rect.Bottom());
+ }
f32 scale_u = static_cast<f32>(framebuffer.width) / static_cast<f32>(screen_info.width);
f32 scale_v = static_cast<f32>(framebuffer.height) / static_cast<f32>(screen_info.height);
-
// Scale the output by the crop width/height. This is commonly used with 1280x720 rendering
// (e.g. handheld mode) on a 1920x1080 framebuffer.
if (!fsr) {
@@ -1426,10 +1429,13 @@ void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig&
const auto y = static_cast<f32>(screen.top);
const auto w = static_cast<f32>(screen.GetWidth());
const auto h = static_cast<f32>(screen.GetHeight());
- data.vertices[0] = ScreenRectVertex(x, y, texcoords.top * scale_u, left * scale_v);
- data.vertices[1] = ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left * scale_v);
- data.vertices[2] = ScreenRectVertex(x, y + h, texcoords.top * scale_u, right * scale_v);
- data.vertices[3] = ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v);
+ data.vertices[0] = ScreenRectVertex(x, y, texcoords.top * scale_u, left_start + left * scale_v);
+ data.vertices[1] =
+ ScreenRectVertex(x + w, y, texcoords.bottom * scale_u, left_start + left * scale_v);
+ data.vertices[2] =
+ ScreenRectVertex(x, y + h, texcoords.top * scale_u, left_start + right * scale_v);
+ data.vertices[3] =
+ ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, left_start + right * scale_v);
}
void BlitScreen::CreateFSR() {
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 16e46d3e5..7e40c2df1 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -69,10 +69,17 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
const float width = conv(src.scale_x * 2.0f);
float y = conv(src.translate_y - src.scale_y);
float height = conv(src.scale_y * 2.0f);
- if (regs.screen_y_control.y_negate) {
+ bool y_negate = regs.screen_y_control.y_negate;
+
+ if (!device.IsNvViewportSwizzleSupported()) {
+ y_negate = y_negate != (src.swizzle.y == Maxwell::ViewportSwizzle::NegativeY);
+ }
+
+ if (y_negate) {
y += height;
height = -height;
}
+
const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
VkViewport viewport{
.x = x,
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index fa8efd22e..a69ae7725 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -33,9 +33,10 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)
}
VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
- // Mailbox doesn't lock the application like fifo (vsync), prefer it
+ // Mailbox (triple buffering) doesn't lock the application like fifo (vsync),
+ // prefer it if vsync option is not selected
const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR);
- if (found_mailbox != modes.end()) {
+ if (found_mailbox != modes.end() && !Settings::values.use_vsync.GetValue()) {
return VK_PRESENT_MODE_MAILBOX_KHR;
}
if (!Settings::values.use_speed_limit.GetValue()) {
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp
index 4b1101f7c..164e4ee0e 100644
--- a/src/video_core/shader_cache.cpp
+++ b/src/video_core/shader_cache.cpp
@@ -123,8 +123,8 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
const VAddr addr_end = addr + size;
Entry* const entry = NewEntry(addr, addr_end, data.get());
- const u64 page_end = (addr_end + PAGE_SIZE - 1) >> PAGE_BITS;
- for (u64 page = addr >> PAGE_BITS; page < page_end; ++page) {
+ const u64 page_end = (addr_end + YUZU_PAGESIZE - 1) >> YUZU_PAGEBITS;
+ for (u64 page = addr >> YUZU_PAGEBITS; page < page_end; ++page) {
invalidation_cache[page].push_back(entry);
}
@@ -135,8 +135,8 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
const VAddr addr_end = addr + size;
- const u64 page_end = (addr_end + PAGE_SIZE - 1) >> PAGE_BITS;
- for (u64 page = addr >> PAGE_BITS; page < page_end; ++page) {
+ const u64 page_end = (addr_end + YUZU_PAGESIZE - 1) >> YUZU_PAGEBITS;
+ for (u64 page = addr >> YUZU_PAGEBITS; page < page_end; ++page) {
auto it = invalidation_cache.find(page);
if (it == invalidation_cache.end()) {
continue;
@@ -189,8 +189,8 @@ void ShaderCache::InvalidatePageEntries(std::vector<Entry*>& entries, VAddr addr
}
void ShaderCache::RemoveEntryFromInvalidationCache(const Entry* entry) {
- const u64 page_end = (entry->addr_end + PAGE_SIZE - 1) >> PAGE_BITS;
- for (u64 page = entry->addr_start >> PAGE_BITS; page < page_end; ++page) {
+ const u64 page_end = (entry->addr_end + YUZU_PAGESIZE - 1) >> YUZU_PAGEBITS;
+ for (u64 page = entry->addr_start >> YUZU_PAGEBITS; page < page_end; ++page) {
const auto entries_it = invalidation_cache.find(page);
ASSERT(entries_it != invalidation_cache.end());
std::vector<Entry*>& entries = entries_it->second;
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h
index 1109cfe83..f67cea8c4 100644
--- a/src/video_core/shader_cache.h
+++ b/src/video_core/shader_cache.h
@@ -29,8 +29,8 @@ struct ShaderInfo {
};
class ShaderCache {
- static constexpr u64 PAGE_BITS = 14;
- static constexpr u64 PAGE_SIZE = u64(1) << PAGE_BITS;
+ static constexpr u64 YUZU_PAGEBITS = 14;
+ static constexpr u64 YUZU_PAGESIZE = u64(1) << YUZU_PAGEBITS;
static constexpr size_t NUM_PROGRAMS = 6;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cf3ca06a6..1dbe01bc0 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -589,7 +589,7 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
template <class P>
typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(VAddr cpu_addr) {
// TODO: Properly implement this
- const auto it = page_table.find(cpu_addr >> PAGE_BITS);
+ const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
if (it == page_table.end()) {
return nullptr;
}
@@ -1485,14 +1485,14 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>>& selected_page_table) {
const auto page_it = selected_page_table.find(page);
if (page_it == selected_page_table.end()) {
- ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
+ ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS);
return;
}
std::vector<ImageId>& image_ids = page_it->second;
const auto vector_it = std::ranges::find(image_ids, image_id);
if (vector_it == image_ids.end()) {
ASSERT_MSG(false, "Unregistering unregistered image in page=0x{:x}",
- page << PAGE_BITS);
+ page << YUZU_PAGEBITS);
return;
}
image_ids.erase(vector_it);
@@ -1504,14 +1504,14 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, [this, map_id](u64 page) {
const auto page_it = page_table.find(page);
if (page_it == page_table.end()) {
- ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
+ ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS);
return;
}
std::vector<ImageMapId>& image_map_ids = page_it->second;
const auto vector_it = std::ranges::find(image_map_ids, map_id);
if (vector_it == image_map_ids.end()) {
ASSERT_MSG(false, "Unregistering unregistered image in page=0x{:x}",
- page << PAGE_BITS);
+ page << YUZU_PAGEBITS);
return;
}
image_map_ids.erase(vector_it);
@@ -1532,7 +1532,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) {
const auto page_it = page_table.find(page);
if (page_it == page_table.end()) {
- ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
+ ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS);
return;
}
std::vector<ImageMapId>& image_map_ids = page_it->second;
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index e2f8f84c9..7e6c6cef2 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -47,7 +47,7 @@ struct ImageViewInOut {
template <class P>
class TextureCache {
/// Address shift for caching images into a hash table
- static constexpr u64 PAGE_BITS = 20;
+ static constexpr u64 YUZU_PAGEBITS = 20;
/// Enables debugging features to the texture cache
static constexpr bool ENABLE_VALIDATION = P::ENABLE_VALIDATION;
@@ -178,8 +178,8 @@ private:
template <typename Func>
static void ForEachCPUPage(VAddr addr, size_t size, Func&& func) {
static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>;
- const u64 page_end = (addr + size - 1) >> PAGE_BITS;
- for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) {
+ const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS;
+ for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) {
if constexpr (RETURNS_BOOL) {
if (func(page)) {
break;
@@ -193,8 +193,8 @@ private:
template <typename Func>
static void ForEachGPUPage(GPUVAddr addr, size_t size, Func&& func) {
static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>;
- const u64 page_end = (addr + size - 1) >> PAGE_BITS;
- for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) {
+ const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS;
+ for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) {
if constexpr (RETURNS_BOOL) {
if (func(page)) {
break;
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 9b6b8527b..913f8ebcb 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -15,6 +15,24 @@
namespace Tegra::Texture {
namespace {
+template <u32 mask>
+constexpr u32 pdep(u32 value) {
+ u32 result = 0;
+ u32 m = mask;
+ for (u32 bit = 1; m; bit += bit) {
+ if (value & bit)
+ result |= m & -m;
+ m &= m - 1;
+ }
+ return result;
+}
+
+template <u32 mask, u32 incr_amount>
+void incrpdep(u32& value) {
+ constexpr u32 swizzled_incr = pdep<mask>(incr_amount);
+ value = ((value | ~mask) + swizzled_incr) & mask;
+}
+
template <bool TO_LINEAR, u32 BYTES_PER_PIXEL>
void SwizzleImpl(std::span<u8> output, std::span<const u8> input, u32 width, u32 height, u32 depth,
u32 block_height, u32 block_depth, u32 stride_alignment) {
@@ -44,18 +62,20 @@ void SwizzleImpl(std::span<u8> output, std::span<const u8> input, u32 width, u32
((z & block_depth_mask) << (GOB_SIZE_SHIFT + block_height));
for (u32 line = 0; line < height; ++line) {
const u32 y = line + origin_y;
- const auto& table = SWIZZLE_TABLE[y % GOB_SIZE_Y];
+ const u32 swizzled_y = pdep<SWIZZLE_Y_BITS>(y);
const u32 block_y = y >> GOB_SIZE_Y_SHIFT;
const u32 offset_y = (block_y >> block_height) * block_size +
((block_y & block_height_mask) << GOB_SIZE_SHIFT);
- for (u32 column = 0; column < width; ++column) {
+ u32 swizzled_x = pdep<SWIZZLE_X_BITS>(origin_x * BYTES_PER_PIXEL);
+ for (u32 column = 0; column < width;
+ ++column, incrpdep<SWIZZLE_X_BITS, BYTES_PER_PIXEL>(swizzled_x)) {
const u32 x = (column + origin_x) * BYTES_PER_PIXEL;
const u32 offset_x = (x >> GOB_SIZE_X_SHIFT) << x_shift;
const u32 base_swizzled_offset = offset_z + offset_y + offset_x;
- const u32 swizzled_offset = base_swizzled_offset + table[x % GOB_SIZE_X];
+ const u32 swizzled_offset = base_swizzled_offset + (swizzled_x | swizzled_y);
const u32 unswizzled_offset =
slice * pitch * height + line * pitch + column * BYTES_PER_PIXEL;
@@ -103,12 +123,15 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32
const u32 gob_address_y =
(dst_y / (GOB_SIZE_Y * block_height)) * GOB_SIZE * block_height * image_width_in_gobs +
((dst_y % (GOB_SIZE_Y * block_height)) / GOB_SIZE_Y) * GOB_SIZE;
- const auto& table = SWIZZLE_TABLE[dst_y % GOB_SIZE_Y];
- for (u32 x = 0; x < subrect_width; ++x) {
+
+ const u32 swizzled_y = pdep<SWIZZLE_Y_BITS>(dst_y);
+ u32 swizzled_x = pdep<SWIZZLE_X_BITS>(offset_x * BYTES_PER_PIXEL);
+ for (u32 x = 0; x < subrect_width;
+ ++x, incrpdep<SWIZZLE_X_BITS, BYTES_PER_PIXEL>(swizzled_x)) {
const u32 dst_x = x + offset_x;
const u32 gob_address =
gob_address_y + (dst_x * BYTES_PER_PIXEL / GOB_SIZE_X) * GOB_SIZE * block_height;
- const u32 swizzled_offset = gob_address + table[(dst_x * BYTES_PER_PIXEL) % GOB_SIZE_X];
+ const u32 swizzled_offset = gob_address + (swizzled_x | swizzled_y);
const u32 unswizzled_offset = line * source_pitch + x * BYTES_PER_PIXEL;
const u8* const source_line = unswizzled_data + unswizzled_offset;
@@ -130,16 +153,19 @@ void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width,
for (u32 line = 0; line < line_count; ++line) {
const u32 src_y = line + origin_y;
- const auto& table = SWIZZLE_TABLE[src_y % GOB_SIZE_Y];
+ const u32 swizzled_y = pdep<SWIZZLE_Y_BITS>(src_y);
const u32 block_y = src_y >> GOB_SIZE_Y_SHIFT;
const u32 src_offset_y = (block_y >> block_height) * block_size +
((block_y & block_height_mask) << GOB_SIZE_SHIFT);
- for (u32 column = 0; column < line_length_in; ++column) {
+
+ u32 swizzled_x = pdep<SWIZZLE_X_BITS>(origin_x * BYTES_PER_PIXEL);
+ for (u32 column = 0; column < line_length_in;
+ ++column, incrpdep<SWIZZLE_X_BITS, BYTES_PER_PIXEL>(swizzled_x)) {
const u32 src_x = (column + origin_x) * BYTES_PER_PIXEL;
const u32 src_offset_x = (src_x >> GOB_SIZE_X_SHIFT) << x_shift;
- const u32 swizzled_offset = src_offset_y + src_offset_x + table[src_x % GOB_SIZE_X];
+ const u32 swizzled_offset = src_offset_y + src_offset_x + (swizzled_x | swizzled_y);
const u32 unswizzled_offset = line * pitch + column * BYTES_PER_PIXEL;
std::memcpy(output + unswizzled_offset, input + swizzled_offset, BYTES_PER_PIXEL);
@@ -162,13 +188,15 @@ void SwizzleSliceToVoxel(u32 line_length_in, u32 line_count, u32 pitch, u32 widt
const u32 x_shift = static_cast<u32>(GOB_SIZE_SHIFT) + block_height + block_depth;
for (u32 line = 0; line < line_count; ++line) {
- const auto& table = SWIZZLE_TABLE[line % GOB_SIZE_Y];
+ const u32 swizzled_y = pdep<SWIZZLE_Y_BITS>(line);
const u32 block_y = line / GOB_SIZE_Y;
const u32 dst_offset_y =
(block_y >> block_height) * block_size + (block_y & block_height_mask) * GOB_SIZE;
- for (u32 x = 0; x < line_length_in; ++x) {
+
+ u32 swizzled_x = 0;
+ for (u32 x = 0; x < line_length_in; ++x, incrpdep<SWIZZLE_X_BITS, 1>(swizzled_x)) {
const u32 dst_offset =
- ((x / GOB_SIZE_X) << x_shift) + dst_offset_y + table[x % GOB_SIZE_X];
+ ((x / GOB_SIZE_X) << x_shift) + dst_offset_y + (swizzled_x | swizzled_y);
const u32 src_offset = x * BYTES_PER_PIXEL + line * pitch;
std::memcpy(output + dst_offset, input + src_offset, BYTES_PER_PIXEL);
}
@@ -267,11 +295,13 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32
const std::size_t gob_address_y =
(y / (GOB_SIZE_Y * block_height)) * GOB_SIZE * block_height * image_width_in_gobs +
((y % (GOB_SIZE_Y * block_height)) / GOB_SIZE_Y) * GOB_SIZE;
- const auto& table = SWIZZLE_TABLE[y % GOB_SIZE_Y];
- for (std::size_t x = dst_x; x < width && count < copy_size; ++x) {
+ const u32 swizzled_y = pdep<SWIZZLE_Y_BITS>(static_cast<u32>(y));
+ u32 swizzled_x = pdep<SWIZZLE_X_BITS>(dst_x);
+ for (std::size_t x = dst_x; x < width && count < copy_size;
+ ++x, incrpdep<SWIZZLE_X_BITS, 1>(swizzled_x)) {
const std::size_t gob_address =
gob_address_y + (x / GOB_SIZE_X) * GOB_SIZE * block_height;
- const std::size_t swizzled_offset = gob_address + table[x % GOB_SIZE_X];
+ const std::size_t swizzled_offset = gob_address + (swizzled_x | swizzled_y);
const u8* source_line = source_data + count;
u8* dest_addr = swizzle_data + swizzled_offset;
count++;
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 59dfd1621..31a11708f 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -20,6 +20,9 @@ constexpr u32 GOB_SIZE_Y_SHIFT = 3;
constexpr u32 GOB_SIZE_Z_SHIFT = 0;
constexpr u32 GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT;
+constexpr u32 SWIZZLE_X_BITS = 0b100101111;
+constexpr u32 SWIZZLE_Y_BITS = 0b011010000;
+
using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>;
/**