diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 14b0c521e..67994485a 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -191,7 +191,7 @@ void PipelineCache::RefreshGraphicsKey() { LiverpoolToVK::SurfaceFormat(col_buf.info.format, col_buf.NumFormat()); const auto is_vo_surface = renderer->IsVideoOutSurface(col_buf); key.color_formats[remapped_cb] = LiverpoolToVK::AdjustColorBufferFormat( - base_format, col_buf.info.comp_swap.Value(), false/*is_vo_surface*/); + base_format, col_buf.info.comp_swap.Value(), false /*is_vo_surface*/); key.blend_controls[remapped_cb] = regs.blend_control[cb]; key.blend_controls[remapped_cb].enable.Assign(key.blend_controls[remapped_cb].enable && !col_buf.info.blend_bypass); diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 881002243..f7aef8471 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -117,6 +117,8 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, image{instance->GetDevice(), instance->GetAllocator()}, cpu_addr{info.guest_address}, cpu_addr_end{cpu_addr + info.guest_size_bytes} { ASSERT(info.pixel_format != vk::Format::eUndefined); + // Here we force `eExtendedUsage` as don't know all image usage cases beforehand. In normal case + // the texture cache should re-create the resource with the usage requested vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlagBits::eExtendedUsage}; if (info.props.is_cube) { @@ -124,9 +126,6 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, } else if (info.props.is_volume) { flags |= vk::ImageCreateFlagBits::e2DArrayCompatible; } - if (info.IsBlockCoded()) { - flags |= vk::ImageCreateFlagBits::eBlockTexelViewCompatible; - } usage = ImageUsageFlags(info); diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index d1489d02c..9131e6f1f 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -198,7 +198,31 @@ ImageView& TextureCache::FindTexture(const ImageInfo& info, const ImageViewInfo& usage.texture = true; } - return RegisterImageView(image_id, view_info); + // These changes are temporary and should be removed once texture cache will handle subresources + // merging + auto view_info_tmp = view_info; + if (view_info_tmp.range.base.level > image.info.resources.levels - 1 || + view_info_tmp.range.base.layer > image.info.resources.layers - 1 || + view_info_tmp.range.extent.levels > image.info.resources.levels || + view_info_tmp.range.extent.layers > image.info.resources.layers) { + + LOG_ERROR(Render_Vulkan, + "Subresource range ({}~{},{}~{}) exceeds base image extents ({},{})", + view_info_tmp.range.base.level, view_info_tmp.range.extent.levels, + view_info_tmp.range.base.layer, view_info_tmp.range.extent.layers, + image.info.resources.levels, image.info.resources.layers); + + view_info_tmp.range.base.level = + std::min(view_info_tmp.range.base.level, image.info.resources.levels - 1); + view_info_tmp.range.base.layer = + std::min(view_info_tmp.range.base.layer, image.info.resources.layers - 1); + view_info_tmp.range.extent.levels = + std::min(view_info_tmp.range.extent.levels, image.info.resources.levels); + view_info_tmp.range.extent.layers = + std::min(view_info_tmp.range.extent.layers, image.info.resources.layers); + } + + return RegisterImageView(image_id, view_info_tmp); } ImageView& TextureCache::FindRenderTarget(const ImageInfo& image_info, diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index edd8618b4..32089423d 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -374,11 +374,14 @@ std::optional TileManager::TryDetile(Image& image) { auto in_buffer = AllocBuffer(image.info.guest_size_bytes); Upload(in_buffer, reinterpret_cast(image.info.guest_address), image.info.guest_size_bytes); - scheduler.DeferOperation([=, this]() { FreeBuffer(in_buffer); }); // Prepare output buffer auto out_buffer = AllocBuffer(image.info.guest_size_bytes, true); - scheduler.DeferOperation([=, this]() { FreeBuffer(out_buffer); }); + + scheduler.DeferOperation([=, this]() { + FreeBuffer(in_buffer); + FreeBuffer(out_buffer); + }); auto cmdbuf = scheduler.CommandBuffer(); cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, *detiler->pl); @@ -433,9 +436,19 @@ std::optional TileManager::TryDetile(Image& image) { ASSERT((image.info.guest_size_bytes % 64) == 0); const auto bpp = image.info.num_bits * (image.info.props.is_block ? 16u : 1u); - auto num_tiles = image.info.guest_size_bytes / (64 * (bpp / 8)); + const auto num_tiles = image.info.guest_size_bytes / (64 * (bpp / 8)); cmdbuf.dispatch(num_tiles, 1, 1); + const vk::BufferMemoryBarrier post_barrier{ + .srcAccessMask = vk::AccessFlagBits::eShaderWrite, + .dstAccessMask = vk::AccessFlagBits::eTransferRead, + .buffer = out_buffer.first, + .size = image.info.guest_size_bytes, + }; + cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader, + vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion, + {}, post_barrier, {}); + return {out_buffer.first}; }