diff --git a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp index d1fc5a4764..eb5f11ce03 100644 --- a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp +++ b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp @@ -45,7 +45,7 @@ namespace vk for (const auto& e : image_list) { const VkImageSubresourceRange subres = { e->aspect(), 0, 1, 0, 1 }; - image_views.push_back(std::make_unique(dev, e, VK_IMAGE_VIEW_TYPE_2D, vk::default_component_map, subres)); + image_views.push_back(std::make_unique(dev, e, e->format(), VK_IMAGE_VIEW_TYPE_2D, vk::default_component_map, subres)); } auto value = std::make_unique(dev, renderpass, width, height, std::move(image_views)); diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp index 9d66baa9d2..0bd7852c2d 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp @@ -911,15 +911,15 @@ namespace vk m_cyclic_ref_tracker.reset(); } - image_view* render_target::get_view(const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask) + image_view* render_target::get_view(VkFormat format, const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask) { if (remap.encoded == VK_REMAP_VIEW_MULTISAMPLED) { // Special remap flag, intercept here - return vk::viewable_image::get_view(remap.with_encoding(VK_REMAP_IDENTITY), mask); + return vk::viewable_image::get_view(format, remap.with_encoding(VK_REMAP_IDENTITY), mask); } - return vk::viewable_image::get_view(remap, mask); + return vk::viewable_image::get_view(format, remap, mask); } void render_target::memory_barrier(vk::command_buffer& cmd, rsx::surface_access access) diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 3c3ef0acbd..287c9c2c52 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -110,7 +110,7 @@ namespace vk bool matches_dimensions(u16 _width, u16 _height) const; void reset_surface_counters(); - image_view* get_view(const rsx::texture_channel_remap_t& remap, + image_view* get_view(VkFormat format, const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) override; // Memory management diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.cpp b/rpcs3/Emu/RSX/VK/vkutils/image.cpp index 5e4c8ce022..ce431945ed 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/image.cpp @@ -333,10 +333,10 @@ namespace vk create_impl(); } - image_view::image_view(VkDevice dev, vk::image* resource, VkImageViewType view_type, const VkComponentMapping& mapping, const VkImageSubresourceRange& range) + image_view::image_view(VkDevice dev, vk::image* resource, VkFormat format, VkImageViewType view_type, const VkComponentMapping& mapping, const VkImageSubresourceRange& range) : m_device(dev), m_resource(resource) { - info.format = resource->info.format; + info.format = format == VK_FORMAT_UNDEFINED ? resource->format() : format; info.image = resource->value; info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; info.components = mapping; @@ -379,6 +379,33 @@ namespace vk vkDestroyImageView(m_device, value, nullptr); } + image_view* image_view::as(VkFormat format) + { + if (this->format() == format) + { + return this; + } + + auto self = this->m_root_view + ? this->m_root_view + : this; + + if (auto found = self->m_subviews.find(format); + found != self->m_subviews.end()) + { + return found->second.get(); + } + + // Create a derived + auto view = std::make_unique(m_device, info.image, info.viewType, format, info.components, info.subresourceRange); + view->m_resource = self->m_resource; + view->m_root_view = self; + + auto ret = view.get(); + self->m_subviews.emplace(format, std::move(view)); + return ret; + } + u32 image_view::encoded_component_map() const { #if (VK_DISABLE_COMPONENT_SWIZZLE) @@ -436,7 +463,7 @@ namespace vk return result; } - image_view* viewable_image::get_view(const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask) + image_view* viewable_image::get_view(VkFormat format, const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask) { u32 remap_encoding = remap.encoded; if (remap_encoding == VK_REMAP_IDENTITY) @@ -479,7 +506,7 @@ namespace vk const VkImageSubresourceRange range = { aspect() & mask, 0, info.mipLevels, 0, info.arrayLayers }; ensure(range.aspectMask); - auto view = std::make_unique(*g_render_device, this, VK_IMAGE_VIEW_TYPE_MAX_ENUM, real_mapping, range); + auto view = std::make_unique(*g_render_device, this, format, VK_IMAGE_VIEW_TYPE_MAX_ENUM, real_mapping, range); auto result = view.get(); views.emplace(storage_key, std::move(view)); return result; diff --git a/rpcs3/Emu/RSX/VK/vkutils/image.h b/rpcs3/Emu/RSX/VK/vkutils/image.h index fbe7abb5fd..e494f9e40d 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/image.h +++ b/rpcs3/Emu/RSX/VK/vkutils/image.h @@ -112,21 +112,29 @@ namespace vk image_view(VkDevice dev, VkImageViewCreateInfo create_info); image_view(VkDevice dev, vk::image* resource, + VkFormat format = VK_FORMAT_UNDEFINED, VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_MAX_ENUM, const VkComponentMapping& mapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }, const VkImageSubresourceRange& range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); ~image_view(); + vk::image_view* as(VkFormat new_format); + u32 encoded_component_map() const; vk::image* image() const; image_view(const image_view&) = delete; image_view(image_view&&) = delete; + VkFormat format() const { return info.format; } + private: + std::unordered_map> m_subviews; + VkDevice m_device; vk::image* m_resource = nullptr; + vk::image_view* m_root_view = nullptr; void create_impl(); void set_debug_name(std::string_view name); @@ -141,9 +149,18 @@ namespace vk public: using image::image; - virtual image_view* get_view(const rsx::texture_channel_remap_t& remap, + virtual image_view* get_view( + VkFormat format, + const rsx::texture_channel_remap_t& remap, VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT); + image_view* get_view( + const rsx::texture_channel_remap_t& remap, + VkImageAspectFlags mask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) + { + return get_view(info.format, remap, mask); + } + void set_native_component_layout(VkComponentMapping new_layout); }; }