diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index a0899f7c8..ec099b9f6 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -52,7 +52,8 @@ bool Rasterizer::FilterDraw() { // There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an // actual draw hence can skip pipeline creation. if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::EliminateFastClear) { - LOG_TRACE(Render_Vulkan, "FCE pass skipped"); + // Clears the render target if FCE is launched before any draws + EliminateFastClear(); return false; } if (regs.color_control.mode == Liverpool::ColorControl::OperationMode::FmaskDecompress) { @@ -201,6 +202,34 @@ RenderState Rasterizer::PrepareRenderState(u32 mrt_mask) { return {vertex_offset, instance_offset}; } +void Rasterizer::EliminateFastClear() { + auto& col_buf = liverpool->regs.color_buffers[0]; + if (!col_buf || !col_buf.info.fast_clear) { + return; + } + if (!texture_cache.IsMetaCleared(col_buf.CmaskAddress(), col_buf.view.slice_start)) { + return; + } + for (u32 slice = col_buf.view.slice_start; slice <= col_buf.view.slice_max; ++slice) { + texture_cache.TouchMeta(col_buf.CmaskAddress(), slice, false); + } + const auto& hint = liverpool->last_cb_extent[0]; + VideoCore::TextureCache::RenderTargetDesc desc(col_buf, hint); + const auto& image_view = texture_cache.FindRenderTarget(desc); + const auto& image = texture_cache.GetImage(image_view.image_id); + const vk::ImageSubresourceRange range = { + .aspectMask = vk::ImageAspectFlagBits::eColor, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = col_buf.view.slice_start, + .layerCount = col_buf.view.slice_max - col_buf.view.slice_start + 1, + }; + scheduler.EndRendering(); + scheduler.CommandBuffer().clearColorImage(image.image, vk::ImageLayout::eColorAttachmentOptimal, + LiverpoolToVK::ColorBufferClearValue(col_buf).color, + range); +} + void Rasterizer::Draw(bool is_indexed, u32 index_offset) { RENDERER_TRACE; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 80b22c7d8..1bbb90b6c 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -71,6 +71,7 @@ private: RenderState PrepareRenderState(u32 mrt_mask); void BeginRendering(const GraphicsPipeline& pipeline, RenderState& state); void Resolve(); + void EliminateFastClear(); void UpdateDynamicState(const GraphicsPipeline& pipeline); void UpdateViewportScissorState();