diff options
| author | 2023-09-20 19:57:47 +0300 | |
|---|---|---|
| committer | 2023-09-25 09:20:32 -0400 | |
| commit | 5e4938ab1a8dbc121b522a292d230a274a03cfed (patch) | |
| tree | f6cac92fcf3f261dad3dd77285d6de6aef75df8e /src | |
| parent | Merge pull request #11225 from FernandoS27/no-laxatives-in-santas-cookies (diff) | |
| download | yuzu-5e4938ab1a8dbc121b522a292d230a274a03cfed.tar.gz yuzu-5e4938ab1a8dbc121b522a292d230a274a03cfed.tar.xz yuzu-5e4938ab1a8dbc121b522a292d230a274a03cfed.zip | |
renderer_vulkan: Implement MSAA copies
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pass.cpp | 139 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pass.h | 19 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 81 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 7 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 5 |
5 files changed, 219 insertions, 32 deletions
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 289d5b25c..617f92910 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <array> | 4 | #include <array> |
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <numeric> | ||
| 6 | #include <optional> | 7 | #include <optional> |
| 7 | #include <utility> | 8 | #include <utility> |
| 8 | 9 | ||
| @@ -11,7 +12,10 @@ | |||
| 11 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | #include "common/div_ceil.h" | 14 | #include "common/div_ceil.h" |
| 15 | #include "common/vector_math.h" | ||
| 14 | #include "video_core/host_shaders/astc_decoder_comp_spv.h" | 16 | #include "video_core/host_shaders/astc_decoder_comp_spv.h" |
| 17 | #include "video_core/host_shaders/convert_msaa_to_non_msaa_comp_spv.h" | ||
| 18 | #include "video_core/host_shaders/convert_non_msaa_to_msaa_comp_spv.h" | ||
| 15 | #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" | 19 | #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" |
| 16 | #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" | 20 | #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" |
| 17 | #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" | 21 | #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" |
| @@ -131,6 +135,33 @@ constexpr DescriptorBankInfo ASTC_BANK_INFO{ | |||
| 131 | .score = 2, | 135 | .score = 2, |
| 132 | }; | 136 | }; |
| 133 | 137 | ||
| 138 | constexpr std::array<VkDescriptorSetLayoutBinding, ASTC_NUM_BINDINGS> MSAA_DESCRIPTOR_SET_BINDINGS{{ | ||
| 139 | { | ||
| 140 | .binding = 0, | ||
| 141 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 142 | .descriptorCount = 1, | ||
| 143 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 144 | .pImmutableSamplers = nullptr, | ||
| 145 | }, | ||
| 146 | { | ||
| 147 | .binding = 1, | ||
| 148 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 149 | .descriptorCount = 1, | ||
| 150 | .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 151 | .pImmutableSamplers = nullptr, | ||
| 152 | }, | ||
| 153 | }}; | ||
| 154 | |||
| 155 | constexpr DescriptorBankInfo MSAA_BANK_INFO{ | ||
| 156 | .uniform_buffers = 0, | ||
| 157 | .storage_buffers = 0, | ||
| 158 | .texture_buffers = 0, | ||
| 159 | .image_buffers = 0, | ||
| 160 | .textures = 0, | ||
| 161 | .images = 2, | ||
| 162 | .score = 2, | ||
| 163 | }; | ||
| 164 | |||
| 134 | constexpr VkDescriptorUpdateTemplateEntry INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ | 165 | constexpr VkDescriptorUpdateTemplateEntry INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ |
| 135 | .dstBinding = 0, | 166 | .dstBinding = 0, |
| 136 | .dstArrayElement = 0, | 167 | .dstArrayElement = 0, |
| @@ -149,6 +180,15 @@ constexpr VkDescriptorUpdateTemplateEntry QUERIES_SCAN_DESCRIPTOR_UPDATE_TEMPLAT | |||
| 149 | .stride = sizeof(DescriptorUpdateEntry), | 180 | .stride = sizeof(DescriptorUpdateEntry), |
| 150 | }; | 181 | }; |
| 151 | 182 | ||
| 183 | constexpr VkDescriptorUpdateTemplateEntry MSAA_DESCRIPTOR_UPDATE_TEMPLATE{ | ||
| 184 | .dstBinding = 0, | ||
| 185 | .dstArrayElement = 0, | ||
| 186 | .descriptorCount = 2, | ||
| 187 | .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, | ||
| 188 | .offset = 0, | ||
| 189 | .stride = sizeof(DescriptorUpdateEntry), | ||
| 190 | }; | ||
| 191 | |||
| 152 | constexpr std::array<VkDescriptorUpdateTemplateEntry, ASTC_NUM_BINDINGS> | 192 | constexpr std::array<VkDescriptorUpdateTemplateEntry, ASTC_NUM_BINDINGS> |
| 153 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ | 193 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ |
| 154 | { | 194 | { |
| @@ -224,6 +264,9 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, | |||
| 224 | }); | 264 | }); |
| 225 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); | 265 | descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, bank_info); |
| 226 | } | 266 | } |
| 267 | if (code.empty()) { | ||
| 268 | return; | ||
| 269 | } | ||
| 227 | module = device.GetLogical().CreateShaderModule({ | 270 | module = device.GetLogical().CreateShaderModule({ |
| 228 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | 271 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 229 | .pNext = nullptr, | 272 | .pNext = nullptr, |
| @@ -590,4 +633,100 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, | |||
| 590 | scheduler.Finish(); | 633 | scheduler.Finish(); |
| 591 | } | 634 | } |
| 592 | 635 | ||
| 636 | MSAACopyPass::MSAACopyPass(const Device& device_, Scheduler& scheduler_, | ||
| 637 | DescriptorPool& descriptor_pool_, | ||
| 638 | StagingBufferPool& staging_buffer_pool_, | ||
| 639 | ComputePassDescriptorQueue& compute_pass_descriptor_queue_) | ||
| 640 | : ComputePass(device_, descriptor_pool_, MSAA_DESCRIPTOR_SET_BINDINGS, | ||
| 641 | MSAA_DESCRIPTOR_UPDATE_TEMPLATE, MSAA_BANK_INFO, {}, | ||
| 642 | CONVERT_NON_MSAA_TO_MSAA_COMP_SPV), | ||
| 643 | scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, | ||
| 644 | compute_pass_descriptor_queue{compute_pass_descriptor_queue_} { | ||
| 645 | const auto make_msaa_pipeline = [this](size_t i, std::span<const u32> code) { | ||
| 646 | modules[i] = device.GetLogical().CreateShaderModule({ | ||
| 647 | .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | ||
| 648 | .pNext = nullptr, | ||
| 649 | .flags = 0, | ||
| 650 | .codeSize = static_cast<u32>(code.size_bytes()), | ||
| 651 | .pCode = code.data(), | ||
| 652 | }); | ||
| 653 | pipelines[i] = device.GetLogical().CreateComputePipeline({ | ||
| 654 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | ||
| 655 | .pNext = nullptr, | ||
| 656 | .flags = 0, | ||
| 657 | .stage{ | ||
| 658 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | ||
| 659 | .pNext = nullptr, | ||
| 660 | .flags = 0, | ||
| 661 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | ||
| 662 | .module = *modules[i], | ||
| 663 | .pName = "main", | ||
| 664 | .pSpecializationInfo = nullptr, | ||
| 665 | }, | ||
| 666 | .layout = *layout, | ||
| 667 | .basePipelineHandle = nullptr, | ||
| 668 | .basePipelineIndex = 0, | ||
| 669 | }); | ||
| 670 | }; | ||
| 671 | make_msaa_pipeline(0, CONVERT_NON_MSAA_TO_MSAA_COMP_SPV); | ||
| 672 | make_msaa_pipeline(1, CONVERT_MSAA_TO_NON_MSAA_COMP_SPV); | ||
| 673 | } | ||
| 674 | |||
| 675 | MSAACopyPass::~MSAACopyPass() = default; | ||
| 676 | |||
| 677 | void MSAACopyPass::CopyImage(Image& dst_image, Image& src_image, | ||
| 678 | std::span<const VideoCommon::ImageCopy> copies, | ||
| 679 | bool msaa_to_non_msaa) { | ||
| 680 | const VkPipeline msaa_pipeline = *pipelines[msaa_to_non_msaa ? 1 : 0]; | ||
| 681 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 682 | for (const VideoCommon::ImageCopy& copy : copies) { | ||
| 683 | ASSERT(copy.src_subresource.base_layer == 0); | ||
| 684 | ASSERT(copy.src_subresource.num_layers == 1); | ||
| 685 | ASSERT(copy.dst_subresource.base_layer == 0); | ||
| 686 | ASSERT(copy.dst_subresource.num_layers == 1); | ||
| 687 | |||
| 688 | compute_pass_descriptor_queue.Acquire(); | ||
| 689 | compute_pass_descriptor_queue.AddImage( | ||
| 690 | src_image.StorageImageView(copy.src_subresource.base_level)); | ||
| 691 | compute_pass_descriptor_queue.AddImage( | ||
| 692 | dst_image.StorageImageView(copy.dst_subresource.base_level)); | ||
| 693 | const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()}; | ||
| 694 | |||
| 695 | const Common::Vec3<u32> num_dispatches = { | ||
| 696 | Common::DivCeil(copy.extent.width, 8U), | ||
| 697 | Common::DivCeil(copy.extent.height, 8U), | ||
| 698 | copy.extent.depth, | ||
| 699 | }; | ||
| 700 | |||
| 701 | scheduler.Record([this, dst = dst_image.Handle(), msaa_pipeline, num_dispatches, | ||
| 702 | descriptor_data](vk::CommandBuffer cmdbuf) { | ||
| 703 | const VkDescriptorSet set = descriptor_allocator.Commit(); | ||
| 704 | device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); | ||
| 705 | cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, msaa_pipeline); | ||
| 706 | cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); | ||
| 707 | cmdbuf.Dispatch(num_dispatches.x, num_dispatches.y, num_dispatches.z); | ||
| 708 | const VkImageMemoryBarrier write_barrier{ | ||
| 709 | .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||
| 710 | .pNext = nullptr, | ||
| 711 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | ||
| 712 | .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, | ||
| 713 | .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 714 | .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||
| 715 | .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 716 | .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||
| 717 | .image = dst, | ||
| 718 | .subresourceRange{ | ||
| 719 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 720 | .baseMipLevel = 0, | ||
| 721 | .levelCount = VK_REMAINING_MIP_LEVELS, | ||
| 722 | .baseArrayLayer = 0, | ||
| 723 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 724 | }, | ||
| 725 | }; | ||
| 726 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | ||
| 727 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, write_barrier); | ||
| 728 | }); | ||
| 729 | } | ||
| 730 | } | ||
| 731 | |||
| 593 | } // namespace Vulkan | 732 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 3ff935639..7b8f938c1 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "video_core/engines/maxwell_3d.h" | 11 | #include "video_core/engines/maxwell_3d.h" |
| 12 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 12 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 13 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" | 13 | #include "video_core/renderer_vulkan/vk_update_descriptor.h" |
| 14 | #include "video_core/texture_cache/types.h" | ||
| 14 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 15 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 16 | 17 | ||
| @@ -130,4 +131,22 @@ private: | |||
| 130 | MemoryAllocator& memory_allocator; | 131 | MemoryAllocator& memory_allocator; |
| 131 | }; | 132 | }; |
| 132 | 133 | ||
| 134 | class MSAACopyPass final : public ComputePass { | ||
| 135 | public: | ||
| 136 | explicit MSAACopyPass(const Device& device_, Scheduler& scheduler_, | ||
| 137 | DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, | ||
| 138 | ComputePassDescriptorQueue& compute_pass_descriptor_queue_); | ||
| 139 | ~MSAACopyPass(); | ||
| 140 | |||
| 141 | void CopyImage(Image& dst_image, Image& src_image, | ||
| 142 | std::span<const VideoCommon::ImageCopy> copies, bool msaa_to_non_msaa); | ||
| 143 | |||
| 144 | private: | ||
| 145 | Scheduler& scheduler; | ||
| 146 | StagingBufferPool& staging_buffer_pool; | ||
| 147 | ComputePassDescriptorQueue& compute_pass_descriptor_queue; | ||
| 148 | std::array<vk::ShaderModule, 2> modules; | ||
| 149 | std::array<vk::Pipeline, 2> pipelines; | ||
| 150 | }; | ||
| 151 | |||
| 133 | } // namespace Vulkan | 152 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 1f9e7acaa..71fdec809 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -176,6 +176,36 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) { | |||
| 176 | return allocator.CreateImage(image_ci); | 176 | return allocator.CreateImage(image_ci); |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | [[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image, | ||
| 180 | VkFormat format) { | ||
| 181 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | ||
| 182 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 183 | .pNext = nullptr, | ||
| 184 | .usage = VK_IMAGE_USAGE_STORAGE_BIT, | ||
| 185 | }; | ||
| 186 | return device.CreateImageView(VkImageViewCreateInfo{ | ||
| 187 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | ||
| 188 | .pNext = &storage_image_view_usage_create_info, | ||
| 189 | .flags = 0, | ||
| 190 | .image = image, | ||
| 191 | .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | ||
| 192 | .format = format, | ||
| 193 | .components{ | ||
| 194 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 195 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 196 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 197 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 198 | }, | ||
| 199 | .subresourceRange{ | ||
| 200 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | ||
| 201 | .baseMipLevel = level, | ||
| 202 | .levelCount = 1, | ||
| 203 | .baseArrayLayer = 0, | ||
| 204 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 205 | }, | ||
| 206 | }); | ||
| 207 | } | ||
| 208 | |||
| 179 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { | 209 | [[nodiscard]] VkImageAspectFlags ImageAspectMask(PixelFormat format) { |
| 180 | switch (VideoCore::Surface::GetFormatType(format)) { | 210 | switch (VideoCore::Surface::GetFormatType(format)) { |
| 181 | case VideoCore::Surface::SurfaceType::ColorTexture: | 211 | case VideoCore::Surface::SurfaceType::ColorTexture: |
| @@ -817,6 +847,10 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched | |||
| 817 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, | 847 | astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, |
| 818 | compute_pass_descriptor_queue, memory_allocator); | 848 | compute_pass_descriptor_queue, memory_allocator); |
| 819 | } | 849 | } |
| 850 | if (device.IsStorageImageMultisampleSupported()) { | ||
| 851 | msaa_copy_pass = std::make_unique<MSAACopyPass>( | ||
| 852 | device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue); | ||
| 853 | } | ||
| 820 | if (!device.IsKhrImageFormatListSupported()) { | 854 | if (!device.IsKhrImageFormatListSupported()) { |
| 821 | return; | 855 | return; |
| 822 | } | 856 | } |
| @@ -1285,7 +1319,11 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, | |||
| 1285 | 1319 | ||
| 1286 | void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, | 1320 | void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, |
| 1287 | std::span<const VideoCommon::ImageCopy> copies) { | 1321 | std::span<const VideoCommon::ImageCopy> copies) { |
| 1288 | UNIMPLEMENTED_MSG("Copying images with different samples is not implemented in Vulkan."); | 1322 | const bool msaa_to_non_msaa = src.info.num_samples > 1 && dst.info.num_samples == 1; |
| 1323 | if (msaa_copy_pass) { | ||
| 1324 | return msaa_copy_pass->CopyImage(dst, src, copies, msaa_to_non_msaa); | ||
| 1325 | } | ||
| 1326 | UNIMPLEMENTED_MSG("Copying images with different samples is not supported."); | ||
| 1289 | } | 1327 | } |
| 1290 | 1328 | ||
| 1291 | u64 TextureCacheRuntime::GetDeviceLocalMemory() const { | 1329 | u64 TextureCacheRuntime::GetDeviceLocalMemory() const { |
| @@ -1333,39 +1371,15 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu | |||
| 1333 | if (runtime->device.HasDebuggingToolAttached()) { | 1371 | if (runtime->device.HasDebuggingToolAttached()) { |
| 1334 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); | 1372 | original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); |
| 1335 | } | 1373 | } |
| 1336 | static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ | ||
| 1337 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, | ||
| 1338 | .pNext = nullptr, | ||
| 1339 | .usage = VK_IMAGE_USAGE_STORAGE_BIT, | ||
| 1340 | }; | ||
| 1341 | current_image = *original_image; | 1374 | current_image = *original_image; |
| 1375 | storage_image_views.resize(info.resources.levels); | ||
| 1342 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() && | 1376 | if (IsPixelFormatASTC(info.format) && !runtime->device.IsOptimalAstcSupported() && |
| 1343 | Settings::values.astc_recompression.GetValue() == | 1377 | Settings::values.astc_recompression.GetValue() == |
| 1344 | Settings::AstcRecompression::Uncompressed) { | 1378 | Settings::AstcRecompression::Uncompressed) { |
| 1345 | const auto& device = runtime->device.GetLogical(); | 1379 | const auto& device = runtime->device.GetLogical(); |
| 1346 | storage_image_views.reserve(info.resources.levels); | ||
| 1347 | for (s32 level = 0; level < info.resources.levels; ++level) { | 1380 | for (s32 level = 0; level < info.resources.levels; ++level) { |
| 1348 | storage_image_views.push_back(device.CreateImageView(VkImageViewCreateInfo{ | 1381 | storage_image_views[level] = |
| 1349 | .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, | 1382 | MakeStorageView(device, level, *original_image, VK_FORMAT_A8B8G8R8_UNORM_PACK32); |
| 1350 | .pNext = &storage_image_view_usage_create_info, | ||
| 1351 | .flags = 0, | ||
| 1352 | .image = *original_image, | ||
| 1353 | .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, | ||
| 1354 | .format = VK_FORMAT_A8B8G8R8_UNORM_PACK32, | ||
| 1355 | .components{ | ||
| 1356 | .r = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1357 | .g = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1358 | .b = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1359 | .a = VK_COMPONENT_SWIZZLE_IDENTITY, | ||
| 1360 | }, | ||
| 1361 | .subresourceRange{ | ||
| 1362 | .aspectMask = aspect_mask, | ||
| 1363 | .baseMipLevel = static_cast<u32>(level), | ||
| 1364 | .levelCount = 1, | ||
| 1365 | .baseArrayLayer = 0, | ||
| 1366 | .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||
| 1367 | }, | ||
| 1368 | })); | ||
| 1369 | } | 1383 | } |
| 1370 | } | 1384 | } |
| 1371 | } | 1385 | } |
| @@ -1496,6 +1510,17 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm | |||
| 1496 | DownloadMemory(buffers, offsets, copies); | 1510 | DownloadMemory(buffers, offsets, copies); |
| 1497 | } | 1511 | } |
| 1498 | 1512 | ||
| 1513 | VkImageView Image::StorageImageView(s32 level) noexcept { | ||
| 1514 | auto& view = storage_image_views[level]; | ||
| 1515 | if (!view) { | ||
| 1516 | const auto format_info = | ||
| 1517 | MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format); | ||
| 1518 | view = | ||
| 1519 | MakeStorageView(runtime->device.GetLogical(), level, current_image, format_info.format); | ||
| 1520 | } | ||
| 1521 | return *view; | ||
| 1522 | } | ||
| 1523 | |||
| 1499 | bool Image::IsRescaled() const noexcept { | 1524 | bool Image::IsRescaled() const noexcept { |
| 1500 | return True(flags & ImageFlagBits::Rescaled); | 1525 | return True(flags & ImageFlagBits::Rescaled); |
| 1501 | } | 1526 | } |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 565ce19a9..d6c5a15cc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -117,6 +117,7 @@ public: | |||
| 117 | BlitImageHelper& blit_image_helper; | 117 | BlitImageHelper& blit_image_helper; |
| 118 | RenderPassCache& render_pass_cache; | 118 | RenderPassCache& render_pass_cache; |
| 119 | std::optional<ASTCDecoderPass> astc_decoder_pass; | 119 | std::optional<ASTCDecoderPass> astc_decoder_pass; |
| 120 | std::unique_ptr<MSAACopyPass> msaa_copy_pass; | ||
| 120 | const Settings::ResolutionScalingInfo& resolution; | 121 | const Settings::ResolutionScalingInfo& resolution; |
| 121 | std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats; | 122 | std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats; |
| 122 | 123 | ||
| @@ -161,15 +162,13 @@ public: | |||
| 161 | return aspect_mask; | 162 | return aspect_mask; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | [[nodiscard]] VkImageView StorageImageView(s32 level) const noexcept { | ||
| 165 | return *storage_image_views[level]; | ||
| 166 | } | ||
| 167 | |||
| 168 | /// Returns true when the image is already initialized and mark it as initialized | 165 | /// Returns true when the image is already initialized and mark it as initialized |
| 169 | [[nodiscard]] bool ExchangeInitialization() noexcept { | 166 | [[nodiscard]] bool ExchangeInitialization() noexcept { |
| 170 | return std::exchange(initialized, true); | 167 | return std::exchange(initialized, true); |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 170 | VkImageView StorageImageView(s32 level) noexcept; | ||
| 171 | |||
| 173 | bool IsRescaled() const noexcept; | 172 | bool IsRescaled() const noexcept; |
| 174 | 173 | ||
| 175 | bool ScaleUp(bool ignore = false); | 174 | bool ScaleUp(bool ignore = false); |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 94f41266d..dd1e7ea8c 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -324,6 +324,11 @@ public: | |||
| 324 | return features.shader_float16_int8.shaderInt8; | 324 | return features.shader_float16_int8.shaderInt8; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | /// Returns true if the device supports binding multisample images as storage images. | ||
| 328 | bool IsStorageImageMultisampleSupported() const { | ||
| 329 | return features.features.shaderStorageImageMultisample; | ||
| 330 | } | ||
| 331 | |||
| 327 | /// Returns true if the device warp size can potentially be bigger than guest's warp size. | 332 | /// Returns true if the device warp size can potentially be bigger than guest's warp size. |
| 328 | bool IsWarpSizePotentiallyBiggerThanGuest() const { | 333 | bool IsWarpSizePotentiallyBiggerThanGuest() const { |
| 329 | return is_warp_potentially_bigger; | 334 | return is_warp_potentially_bigger; |