Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,14 @@ class MultisampleTarget {
return clear;
}

void requireDccRange(bool valid, const GuestMemory::UnchangedQuery& range, const char* reason) const {
if (valid) return;
const auto* plane = range.address == target.address ? "color" : range.address == target.dccAddress ? "DCC" : "CMASK";
char text[384];
std::snprintf(text, sizeof(text), "%s (%s range 0x%llx+0x%zx, %u samples)", reason, plane, static_cast<unsigned long long>(range.address), range.bytes, target.samples);
Require(false, text);
}

void checkDccCurrent(const ColorTarget& use) const {
if (dccRanges.empty()) {
Require(use.dccAddress == 0, "adding DCC to a resident multisampled color target is not implemented");
Expand All @@ -342,10 +350,10 @@ class MultisampleTarget {
static_cast<void>(MultisampledDccBytes(use));
Require(use.address == target.address && use.dccAddress == target.dccAddress && use.dccControl == target.dccControl && use.dccAlphaOnMsb == target.dccAlphaOnMsb && use.dccPipeAligned == target.dccPipeAligned && use.cmaskAddress == target.cmaskAddress && use.cmaskBytes == target.cmaskBytes && use.tileMode == target.tileMode && use.elementBytes == target.elementBytes && use.pipeBankXor == target.pipeBankXor, "multisampled DCC target layout or metadata changed");
for (const auto& range : dccRanges) {
Require(GuestMemory::Watched(range.address, range.bytes), "multisampled DCC target reuse requires watched guest memory");
requireDccRange(GuestMemory::Watched(range.address, range.bytes), range, "multisampled DCC target reuse requires watched guest memory");
GuestMemory::CollectWritesUncached(range.address, range.bytes);
Require(GuestMemory::UnchangedSince(range.address, range.bytes, range.generation) || !GuestMemory::StoredOver(range.address, range.bytes, range.generation), "writes to a resident multisampled DCC target or its metadata are not implemented");
if (auto* recorder = Recorder::Active(); recorder != nullptr) Require(!recorder->PendingWriteOverlaps(range.address, range.bytes), "pending writes to a resident multisampled DCC target or its metadata are not implemented");
requireDccRange(GuestMemory::UnchangedSince(range.address, range.bytes, range.generation) || !GuestMemory::StoredOver(range.address, range.bytes, range.generation), range, "writes to a resident multisampled DCC target or its metadata are not implemented");
if (auto* recorder = Recorder::Active(); recorder != nullptr) requireDccRange(!recorder->PendingWriteOverlaps(range.address, range.bytes), range, "pending writes to a resident multisampled DCC target or its metadata are not implemented");
}
}

Expand Down
19 changes: 19 additions & 0 deletions core/libs/prx/libSceAgcDriver/tests/execution/AlphaToCoverage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,11 @@ void DitheredCoverage(AgcDriver::VulkanDevice& device) {

void DccFastClearTests(AgcDriver::VulkanDevice& device, std::uint32_t selectedSamples) {
const ColorTargetLayout layout(Width, Height, ColorTileMode::RenderTarget, 8);
const auto expectRange = [](std::string_view message, const char* plane, std::uint64_t address, std::size_t bytes, std::uint32_t samples) {
char detail[160];
std::snprintf(detail, sizeof(detail), "(%s range 0x%llx+0x%zx, %u samples)", plane, static_cast<unsigned long long>(address), bytes, samples);
Require(message.find(detail) != std::string_view::npos, "a resident multisampled DCC refusal did not identify the affected plane, range and sample count");
};
std::vector<std::unique_ptr<Block>> blocks;
struct ClearTargets {
AgcDriver::VulkanDevice& device;
Expand Down Expand Up @@ -542,6 +547,7 @@ void DccFastClearTests(AgcDriver::VulkanDevice& device, std::uint32_t selectedSa
device.ColorMetadataPass(pass);
} catch (const std::runtime_error& error) {
refused = std::string_view(error.what()).find("writes to a resident multisampled DCC") != std::string_view::npos;
if (refused) expectRange(error.what(), "color", source.Address(), AgcDriver::Graphics::MultisampledColorBytes(target), samples);
}
Require(refused, "a same-value CPU color store did not invalidate multisampled DCC residency");
}
Expand All @@ -552,16 +558,29 @@ void DccFastClearTests(AgcDriver::VulkanDevice& device, std::uint32_t selectedSa
device.ColorMetadataPass(pass);
} catch (const std::runtime_error& error) {
refused = std::string_view(error.what()).find("writes to a resident multisampled DCC") != std::string_view::npos;
if (refused) expectRange(error.what(), "DCC", metadata.Address(), AgcDriver::Graphics::MultisampledDccBytes(target), samples);
}
Require(refused, "a same-value CPU DCC store did not invalidate multisampled DCC residency");
}
if (code == 0x40u && alphaOnMsb && cmaskMode == 0xccu) {
reinterpret_cast<volatile std::uint8_t*>(target.cmaskAddress)[0] = 0xccu;
bool refused = false;
try {
device.ColorMetadataPass(pass);
} catch (const std::runtime_error& error) {
refused = std::string_view(error.what()).find("writes to a resident multisampled DCC") != std::string_view::npos;
if (refused) expectRange(error.what(), "CMASK", target.cmaskAddress, target.cmaskBytes, samples);
}
Require(refused, "a same-value CPU CMASK store did not invalidate multisampled DCC residency");
}
if (code == 0xc0u && alphaOnMsb && cmaskMode == 0) {
AgcDriver::GuestMemory::Unwatch(metadata.Address(), 4096);
bool refused = false;
try {
device.ColorMetadataPass(pass);
} catch (const std::runtime_error& error) {
refused = std::string_view(error.what()).find("reuse requires watched guest memory") != std::string_view::npos;
if (refused) expectRange(error.what(), "DCC", metadata.Address(), AgcDriver::Graphics::MultisampledDccBytes(target), samples);
}
Require(refused, "an unwatched metadata range remained eligible for multisampled DCC reuse");
}
Expand Down
Loading