renderer_vulkan: Fix allocation caching bug
This commit is contained in:
		| @@ -117,20 +117,26 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelForma | |||||||
|     const vk::Format vk_format = is_suitable ? traits.native : traits.fallback; |     const vk::Format vk_format = is_suitable ? traits.native : traits.fallback; | ||||||
|     const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect); |     const vk::ImageUsageFlags vk_usage = is_suitable ? traits.usage : GetImageUsage(aspect); | ||||||
|  |  | ||||||
|     return Allocate(width, height, type, vk_format, vk_usage, |     return Allocate(width, height, format, type, vk_format, vk_usage); | ||||||
|                     format == VideoCore::PixelFormat::RGBA8); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::TextureType type, | ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format, | ||||||
|                                     vk::Format format, vk::ImageUsageFlags usage, |                                     VideoCore::TextureType type, vk::Format format, | ||||||
|                                     bool create_storage_view) { |                                     vk::ImageUsageFlags usage) { | ||||||
|     ImageAlloc alloc{}; |     ImageAlloc alloc{}; | ||||||
|     alloc.format = format; |     alloc.format = format; | ||||||
|     alloc.levels = std::bit_width(std::max(width, height)); |     alloc.levels = std::bit_width(std::max(width, height)); | ||||||
|     alloc.layers = type == VideoCore::TextureType::CubeMap ? 6 : 1; |     alloc.layers = type == VideoCore::TextureType::CubeMap ? 6 : 1; | ||||||
|     alloc.aspect = GetImageAspect(format); |     alloc.aspect = GetImageAspect(format); | ||||||
|  |  | ||||||
|     const HostTextureTag key = {.format = format, .type = type, .width = width, .height = height}; |     // The internal format does not provide enough guarantee of texture uniqueness | ||||||
|  |     // especially when many pixel formats fallback to RGBA8 | ||||||
|  |     ASSERT(pixel_format != VideoCore::PixelFormat::Invalid); | ||||||
|  |     const HostTextureTag key = {.format = format, | ||||||
|  |                                 .pixel_format = pixel_format, | ||||||
|  |                                 .type = type, | ||||||
|  |                                 .width = width, | ||||||
|  |                                 .height = height}; | ||||||
|  |  | ||||||
|     // Attempt to recycle an unused allocation |     // Attempt to recycle an unused allocation | ||||||
|     if (auto it = texture_recycler.find(key); it != texture_recycler.end()) { |     if (auto it = texture_recycler.find(key); it != texture_recycler.end()) { | ||||||
| @@ -139,6 +145,8 @@ ImageAlloc TextureRuntime::Allocate(u32 width, u32 height, VideoCore::TextureTyp | |||||||
|         return alloc; |         return alloc; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     const bool create_storage_view = pixel_format == VideoCore::PixelFormat::RGBA8; | ||||||
|  |  | ||||||
|     vk::ImageCreateFlags flags; |     vk::ImageCreateFlags flags; | ||||||
|     if (type == VideoCore::TextureType::CubeMap) { |     if (type == VideoCore::TextureType::CubeMap) { | ||||||
|         flags |= vk::ImageCreateFlagBits::eCubeCompatible; |         flags |= vk::ImageCreateFlagBits::eCubeCompatible; | ||||||
| @@ -598,13 +606,15 @@ Surface::Surface(const VideoCore::SurfaceParams& params, vk::Format format, | |||||||
|     : VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()}, |     : VideoCore::SurfaceBase<Surface>{params}, runtime{runtime}, instance{runtime.GetInstance()}, | ||||||
|       scheduler{runtime.GetScheduler()} { |       scheduler{runtime.GetScheduler()} { | ||||||
|     if (format != vk::Format::eUndefined) { |     if (format != vk::Format::eUndefined) { | ||||||
|         alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), texture_type, format, usage); |         alloc = runtime.Allocate(GetScaledWidth(), GetScaledHeight(), pixel_format, texture_type, | ||||||
|  |                                  format, usage); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| Surface::~Surface() { | Surface::~Surface() { | ||||||
|     if (pixel_format != VideoCore::PixelFormat::Invalid) { |     if (pixel_format != VideoCore::PixelFormat::Invalid) { | ||||||
|         const HostTextureTag tag = {.format = alloc.format, |         const HostTextureTag tag = {.format = alloc.format, | ||||||
|  |                                     .pixel_format = pixel_format, | ||||||
|                                     .type = texture_type, |                                     .type = texture_type, | ||||||
|                                     .width = GetScaledWidth(), |                                     .width = GetScaledWidth(), | ||||||
|                                     .height = GetScaledHeight()}; |                                     .height = GetScaledHeight()}; | ||||||
| @@ -800,7 +810,9 @@ void Surface::DepthStencilDownload(const VideoCore::BufferTextureCopy& download, | |||||||
|         VideoCore::Rect2D{0, scaled_rect.GetHeight(), scaled_rect.GetWidth(), 0}; |         VideoCore::Rect2D{0, scaled_rect.GetHeight(), scaled_rect.GetWidth(), 0}; | ||||||
|  |  | ||||||
|     // For depth downloads create an R32UI surface and use a compute shader for convert. |     // For depth downloads create an R32UI surface and use a compute shader for convert. | ||||||
|     // Then we blit and download that surface |     // Then we blit and download that surface. | ||||||
|  |     // NOTE: We don't need to set pixel format here since R32Uint automatically gives us | ||||||
|  |     // a storage view. Also the D24S8 creates a unique cache key for it | ||||||
|     SurfaceParams r32_params = *this; |     SurfaceParams r32_params = *this; | ||||||
|     r32_params.width = scaled_rect.GetWidth(); |     r32_params.width = scaled_rect.GetWidth(); | ||||||
|     r32_params.stride = scaled_rect.GetWidth(); |     r32_params.stride = scaled_rect.GetWidth(); | ||||||
|   | |||||||
| @@ -51,6 +51,7 @@ struct ImageAlloc { | |||||||
|  |  | ||||||
| struct HostTextureTag { | struct HostTextureTag { | ||||||
|     vk::Format format = vk::Format::eUndefined; |     vk::Format format = vk::Format::eUndefined; | ||||||
|  |     VideoCore::PixelFormat pixel_format = VideoCore::PixelFormat::Invalid; | ||||||
|     VideoCore::TextureType type = VideoCore::TextureType::Texture2D; |     VideoCore::TextureType type = VideoCore::TextureType::Texture2D; | ||||||
|     u32 width = 1; |     u32 width = 1; | ||||||
|     u32 height = 1; |     u32 height = 1; | ||||||
| @@ -99,9 +100,9 @@ public: | |||||||
|                                       VideoCore::TextureType type); |                                       VideoCore::TextureType type); | ||||||
|  |  | ||||||
|     /// Allocates a vulkan image |     /// Allocates a vulkan image | ||||||
|     [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::TextureType type, |     [[nodiscard]] ImageAlloc Allocate(u32 width, u32 height, VideoCore::PixelFormat pixel_format, | ||||||
|                                       vk::Format format, vk::ImageUsageFlags usage, |                                       VideoCore::TextureType type, vk::Format format, | ||||||
|                                       bool create_storage_view = false); |                                       vk::ImageUsageFlags usage); | ||||||
|  |  | ||||||
|     /// Causes a GPU command flush |     /// Causes a GPU command flush | ||||||
|     void Finish(); |     void Finish(); | ||||||
| @@ -208,7 +209,13 @@ public: | |||||||
|  |  | ||||||
|     /// Returns the R32 image view used for atomic load/store |     /// Returns the R32 image view used for atomic load/store | ||||||
|     vk::ImageView GetStorageView() const { |     vk::ImageView GetStorageView() const { | ||||||
|         ASSERT(alloc.storage_view); |         if (!alloc.storage_view) { | ||||||
|  |             LOG_CRITICAL(Render_Vulkan, | ||||||
|  |                          "Surface with pixel format {} and internal format {} " | ||||||
|  |                          "does not provide requested storage view!", | ||||||
|  |                          VideoCore::PixelFormatAsString(pixel_format), vk::to_string(alloc.format)); | ||||||
|  |             UNREACHABLE(); | ||||||
|  |         } | ||||||
|         return alloc.storage_view; |         return alloc.storage_view; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user