From 8e1a23d971e7b976e4cea2be430349049f55bbb8 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Sun, 25 Sep 2022 16:50:56 +0300 Subject: [PATCH] rasterizer_cache: Explicitely pass end_offset to swizzle functions * This addresses overflow issues --- src/video_core/rasterizer_cache/morton_swizzle.h | 5 ++--- src/video_core/rasterizer_cache/rasterizer_cache.h | 12 ++++++------ src/video_core/rasterizer_cache/utils.cpp | 14 +++++--------- src/video_core/rasterizer_cache/utils.h | 4 ++-- .../renderer_vulkan/vk_texture_runtime.cpp | 3 +++ 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/video_core/rasterizer_cache/morton_swizzle.h b/src/video_core/rasterizer_cache/morton_swizzle.h index 7066c53a9..108c95924 100644 --- a/src/video_core/rasterizer_cache/morton_swizzle.h +++ b/src/video_core/rasterizer_cache/morton_swizzle.h @@ -136,7 +136,7 @@ inline void MortonCopyTile(u32 stride, std::span tile_buffer, std::sp } template -static void MortonCopy(u32 stride, u32 height, u32 start_offset, +static void MortonCopy(u32 stride, u32 height, u32 start_offset, u32 end_offset, std::span linear_buffer, std::span tiled_buffer) { @@ -148,7 +148,6 @@ static void MortonCopy(u32 stride, u32 height, u32 start_offset, // becomes zero for 4-bit textures! constexpr u32 tile_size = GetFormatBpp(format) * 64 / 8; const u32 linear_tile_size = (7 * stride + 8) * aligned_bytes_per_pixel; - const u32 end_offset = start_offset + static_cast(tiled_buffer.size()); // Does this line have any significance? //u32 linear_offset = aligned_bytes_per_pixel - bytes_per_pixel; @@ -216,7 +215,7 @@ static void MortonCopy(u32 stride, u32 height, u32 start_offset, } } -using MortonFunc = void (*)(u32, u32, u32, std::span, std::span); +using MortonFunc = void (*)(u32, u32, u32, u32, std::span, std::span); static constexpr std::array UNSWIZZLE_TABLE = { MortonCopy, // 0 diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.h b/src/video_core/rasterizer_cache/rasterizer_cache.h index 02da9e465..1d2843443 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.h +++ b/src/video_core/rasterizer_cache/rasterizer_cache.h @@ -894,20 +894,20 @@ void RasterizerCache::UploadSurface(const Surface& surface, SurfaceInterval i ASSERT(load_start >= surface->addr && load_end <= surface->end); const auto& staging = runtime.FindStaging( - surface->width * surface->height * GetBytesPerPixel(surface->pixel_format) * 2, true); + surface->width * surface->height * 4, true); MemoryRef source_ptr = VideoCore::g_memory->GetPhysicalRef(info.addr); if (!source_ptr) [[unlikely]] { return; } const auto upload_data = source_ptr.GetWriteBytes(load_end - load_start); - const u32 start_offset = load_start - surface->addr; MICROPROFILE_SCOPE(RasterizerCache_SurfaceLoad); if (surface->is_tiled) { std::vector unswizzled_data(staging.size); - UnswizzleTexture(*surface, start_offset, upload_data, unswizzled_data); + UnswizzleTexture(*surface, load_start - surface->addr, load_end - surface->addr, + upload_data, unswizzled_data); runtime.FormatConvert(surface->pixel_format, true, unswizzled_data, staging.mapped); } else { runtime.FormatConvert(surface->pixel_format, true, upload_data, staging.mapped); @@ -931,7 +931,7 @@ void RasterizerCache::DownloadSurface(const Surface& surface, SurfaceInterval ASSERT(flush_start >= surface->addr && flush_end <= surface->end); const auto& staging = runtime.FindStaging( - surface->width * surface->height * GetBytesPerPixel(surface->pixel_format), false); + surface->width * surface->height * 4, false); const SurfaceParams params = surface->FromInterval(interval); const BufferTextureCopy download = { .buffer_offset = 0, @@ -948,13 +948,13 @@ void RasterizerCache::DownloadSurface(const Surface& surface, SurfaceInterval } const auto download_dest = dest_ptr.GetWriteBytes(flush_end - flush_start); - const u32 start_offset = flush_start - surface->addr; MICROPROFILE_SCOPE(RasterizerCache_SurfaceFlush); if (surface->is_tiled) { std::vector swizzled_data(staging.size); - SwizzleTexture(*surface, start_offset, staging.mapped, swizzled_data); + SwizzleTexture(*surface, flush_start - surface->addr, flush_end - surface->addr, + staging.mapped, swizzled_data); runtime.FormatConvert(surface->pixel_format, false, swizzled_data, download_dest); } else { runtime.FormatConvert(surface->pixel_format, false, staging.mapped, download_dest); diff --git a/src/video_core/rasterizer_cache/utils.cpp b/src/video_core/rasterizer_cache/utils.cpp index c8e4ab1f2..586565b8d 100644 --- a/src/video_core/rasterizer_cache/utils.cpp +++ b/src/video_core/rasterizer_cache/utils.cpp @@ -3,30 +3,26 @@ // Refer to the license.txt file included. #pragma once -#include #include "common/assert.h" -#include "core/memory.h" #include "video_core/texture/texture_decode.h" #include "video_core/rasterizer_cache/morton_swizzle.h" #include "video_core/rasterizer_cache/surface_params.h" #include "video_core/rasterizer_cache/utils.h" -#include "video_core/renderer_opengl/gl_vars.h" -#include "video_core/video_core.h" namespace VideoCore { -void SwizzleTexture(const SurfaceParams& params, u32 start_offset, +void SwizzleTexture(const SurfaceParams& params, u32 start_offset, u32 end_offset, std::span source_linear, std::span dest_tiled) { const u32 func_index = static_cast(params.pixel_format); const MortonFunc SwizzleImpl = SWIZZLE_TABLE[func_index]; - SwizzleImpl(params.stride, params.height, start_offset, source_linear, dest_tiled); + SwizzleImpl(params.stride, params.height, start_offset, end_offset, source_linear, dest_tiled); } -void UnswizzleTexture(const SurfaceParams& params, u32 start_offset, +void UnswizzleTexture(const SurfaceParams& params, u32 start_offset, u32 end_offset, std::span source_tiled, std::span dest_linear) { const u32 func_index = static_cast(params.pixel_format); const MortonFunc UnswizzleImpl = UNSWIZZLE_TABLE[func_index]; - UnswizzleImpl(params.stride, params.height, start_offset, dest_linear, source_tiled); + UnswizzleImpl(params.stride, params.height, start_offset, end_offset, dest_linear, source_tiled); } ClearValue MakeClearValue(SurfaceType type, PixelFormat format, const u8* fill_data) { @@ -68,4 +64,4 @@ ClearValue MakeClearValue(SurfaceType type, PixelFormat format, const u8* fill_d return result; } -} // namespace OpenGL +} // namespace VideoCore diff --git a/src/video_core/rasterizer_cache/utils.h b/src/video_core/rasterizer_cache/utils.h index e26880a04..1de5faca1 100644 --- a/src/video_core/rasterizer_cache/utils.h +++ b/src/video_core/rasterizer_cache/utils.h @@ -44,7 +44,7 @@ class SurfaceParams; [[nodiscard]] ClearValue MakeClearValue(SurfaceType type, PixelFormat format, const u8* fill_data); -void SwizzleTexture(const SurfaceParams& params, u32 start_offset, +void SwizzleTexture(const SurfaceParams& params, u32 start_offset, u32 end_offset, std::span source_linear, std::span dest_tiled); /** @@ -55,7 +55,7 @@ void SwizzleTexture(const SurfaceParams& params, u32 start_offset, * @param source_tiled The source morton swizzled data. * @param dest_linear The output buffer where the generated linear data will be written to. */ -void UnswizzleTexture(const SurfaceParams& params, u32 start_offset, +void UnswizzleTexture(const SurfaceParams& params, u32 start_offset, u32 end_offset, std::span source_tiled, std::span dest_linear); } // namespace VideoCore diff --git a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp index 54e676a5b..155ddfe3f 100644 --- a/src/video_core/renderer_vulkan/vk_texture_runtime.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_runtime.cpp @@ -215,6 +215,8 @@ void TextureRuntime::FormatConvert(VideoCore::PixelFormat format, bool upload, return Pica::Texture::ConvertABGRToRGBA(source, dest); } else if (format == VideoCore::PixelFormat::RGB8 && upload) { return Pica::Texture::ConvertBGRToRGBA(source, dest); + } else if (format == VideoCore::PixelFormat::D24S8 && !upload) { + return; // HACK: Skip depth download } else if (instance.IsFormatSupported(ToVkFormat(format), feature)) { std::memcpy(dest.data(), source.data(), source.size()); } else { @@ -624,6 +626,7 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi copy_regions[region_count++] = copy_region; if (alloc.aspect & vk::ImageAspectFlagBits::eStencil) { + return; // HACK: Skip depth + stencil downloads for now copy_region.bufferOffset += staging.mapped.size(); copy_region.imageSubresource.aspectMask |= vk::ImageAspectFlagBits::eStencil; copy_regions[region_count++] = copy_region;