graphics: materialize fast clears before sampling reused targets

Co-authored-by: Ali Almohaya <AliAlmohaya@gmail.com>
This commit is contained in:
nmzik
2026-10-13 03:21:40 +02:00
parent 40692dfb64
commit 31b7be9ff2
5 changed files with 113 additions and 41 deletions
@@ -236,7 +236,8 @@ void RenderExecutor::ResolveRenderColorTarget(CommandBuffer& buffer, RenderColor
// DCC owns the clear when both planes are enabled; single-sample CMASK stays expanded.
desc.info.metadata.kind = has_dcc ? ImageMetadataKind::Dcc : ImageMetadataKind::Cmask;
desc.info.metadata.range = {has_dcc ? rt.dcc_addr.addr : rt.cmask.addr, metadata_size.size};
desc.info.metadata.clear_word = rt.clear_word0.word0;
desc.info.metadata.clear_word =
rt.clear_word0.word0 | (uint64_t {rt.clear_word1.word1} << 32u);
desc.info.metadata.clear_register_valid = true;
}
desc.view_info.format = target_format.format;
@@ -27,7 +27,7 @@ struct ImageMetadataInfo {
GuestRange range;
ImageMetadataKind kind = ImageMetadataKind::None;
uint32_t control = 0;
uint32_t clear_word = 0;
uint64_t clear_word = 0;
VideoOutCompression compression = VideoOutCompression::Uncompressed;
bool stencil_compressed = false;
bool clear_register_valid = false;
@@ -414,9 +414,10 @@ inline constexpr std::array<VideoOutFormatPolicy, 8> VIDEO_OUT_FORMAT_POLICIES {
return false;
}
[[nodiscard]] inline bool DecodePackedColorClear(vk::Format format, uint32_t packed,
[[nodiscard]] inline bool DecodePackedColorClear(vk::Format format, uint64_t clear_words,
vk::ClearColorValue& clear) {
vk::ClearColorValue next {};
const auto packed = static_cast<uint32_t>(clear_words);
const auto unorm8 = [](uint32_t value) { return static_cast<float>(value & 0xffu) / 255.0f; };
const auto srgb8 = [](uint32_t value) {
const auto encoded = static_cast<float>(value & 0xffu) / 255.0f;
@@ -434,6 +435,10 @@ inline constexpr std::array<VideoOutFormatPolicy, 8> VIDEO_OUT_FORMAT_POLICIES {
(mantissa << 13u));
};
switch (format) {
case vk::Format::eR16G16B16A16Sfloat:
next.float32[2] = float16(static_cast<uint32_t>(clear_words >> 32u));
next.float32[3] = float16(static_cast<uint32_t>(clear_words >> 48u));
[[fallthrough]];
case vk::Format::eR16G16Sfloat:
next.float32[1] = float16(packed >> 16u);
[[fallthrough]];
+2
View File
@@ -196,6 +196,8 @@ private:
std::span<PreparedBindings* const> stages = {});
[[nodiscard]] bool ResolveColorTargets(CommandBuffer& buffer,
uint32_t render_target_slice_offset);
[[nodiscard]] bool ConsumeMetadataColorOperation(CommandBuffer& buffer,
uint32_t render_target_slice_offset);
void BindImage(ImageId id, bool storage);
void BindRenderTarget(ImageId id);
void ResetBindings();
+15 -10
View File
@@ -608,16 +608,19 @@ enum class CbColorMode : uint8_t {
DccDecompress = 6,
};
static bool ConsumeMetadataColorOperation(const CommandBuffer& buffer) {
bool RenderExecutor::ConsumeMetadataColorOperation(CommandBuffer& buffer,
uint32_t render_target_slice_offset) {
const auto& ctx = buffer.GetRegisters();
const auto mode = ctx.GetColorControl().mode;
// These special modes run color-buffer metadata or decompression operations. The shader is a
// vehicle for that operation, and its exported color must not be applied as a normal draw.
// Kyty stores expanded Vulkan images rather than compressed guest surfaces, so no equivalent
// hardware pass is emitted. Tracked DCC clear state is materialized on attachment bind;
// future CMask/FMask support can consume its state through the same TextureCache path.
return mode == static_cast<uint8_t>(CbColorMode::EliminateFastClear) ||
mode == static_cast<uint8_t>(CbColorMode::FmaskDecompress) ||
if (mode == static_cast<uint8_t>(CbColorMode::EliminateFastClear)) {
// FCE can precede any ordinary draw. Discover the target to materialize its native
// clear metadata before the expanded image is sampled.
RenderColorInfo target {};
ResolveRenderColorTarget(buffer, target, render_target_slice_offset, 0, true);
return true;
}
// Metadata/decompression shaders must not export colors into the expanded image.
return mode == static_cast<uint8_t>(CbColorMode::FmaskDecompress) ||
mode == static_cast<uint8_t>(CbColorMode::DccDecompress);
}
@@ -1257,7 +1260,8 @@ void RenderExecutor::DrawIndex(uint64_t submit_id, CommandBuffer& buffer,
return;
}
if (ConsumeMetadataColorOperation(buffer) || DepthStencilCopy(buffer) ||
if (ConsumeMetadataColorOperation(buffer, args.render_target_slice_offset) ||
DepthStencilCopy(buffer) ||
ResolveColorTargets(buffer, args.render_target_slice_offset)) {
ResetBindings();
return;
@@ -1370,7 +1374,8 @@ void RenderExecutor::DrawAuto(uint64_t submit_id, CommandBuffer& buffer, const D
return;
}
if (ConsumeMetadataColorOperation(buffer) || DepthStencilCopy(buffer) ||
if (ConsumeMetadataColorOperation(buffer, args.render_target_slice_offset) ||
DepthStencilCopy(buffer) ||
ResolveColorTargets(buffer, args.render_target_slice_offset)) {
ResetBindings();
return;