test(agc): add unit test for copied writer indirect overlap disambiguation
This commit is contained in:
parent
a057eede19
commit
d906ee2f6d
|
|
@ -20,6 +20,7 @@
|
|||
#include "CacheKey.hpp"
|
||||
#include "Optimization/ResourceProgram.hpp"
|
||||
#include "BdaAbi.hpp"
|
||||
#include "prx/libc/include/GuestAllocations.hpp"
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
#include <spirv/unified1/spirv.hpp>
|
||||
#include <algorithm>
|
||||
|
|
@ -3238,6 +3239,99 @@ void barycentricEmulationTests() {
|
|||
expectFailure([&] { static_cast<void>(BuildBarycentricGeometryShader(vertex, fragment, target, limits)); }, "not exported by the vertex shader");
|
||||
}
|
||||
|
||||
void copiedWriterIndirectOverlapTests() {
|
||||
using namespace ShaderRecompiler;
|
||||
using namespace AgcDriver::Graphics;
|
||||
|
||||
constexpr std::size_t half = 65536;
|
||||
|
||||
void* directBlock = ::operator new(half, std::align_val_t{half});
|
||||
std::memset(directBlock, 0xaa, half);
|
||||
const auto directAddress = reinterpret_cast<std::uintptr_t>(directBlock);
|
||||
|
||||
void* copiedBlock = ::operator new(half, std::align_val_t{half});
|
||||
std::memset(copiedBlock, 0xbb, half);
|
||||
const auto copiedAddress = reinterpret_cast<std::uintptr_t>(copiedBlock);
|
||||
|
||||
{
|
||||
auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix();
|
||||
GuestAllocations::GuestAllocationsAdd_nid_postfix(mutation, directBlock, half, true, true, true);
|
||||
GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation);
|
||||
}
|
||||
|
||||
mock = MockVulkan{};
|
||||
auto context = mockContext();
|
||||
context.hostImportAlignment = half;
|
||||
context.limits.minStorageBufferOffsetAlignment = 16;
|
||||
context.limits.maxStorageBufferRange = 1u << 27;
|
||||
|
||||
{
|
||||
GuestBufferMemory memory(context);
|
||||
memory.AcquireRegistered();
|
||||
Require(HostImportCovers(context, directAddress, half), "direct registered range must be covered by host import");
|
||||
Require(!HostImportCovers(context, copiedAddress, half), "copied unregistered range must NOT be covered by host import");
|
||||
|
||||
memory.AddWritable(copiedAddress, 1024);
|
||||
memory.AddWritable(directAddress, 1024);
|
||||
memory.Upload(false);
|
||||
|
||||
Require(memory.HasCopiedWrites(), "writer with one copied region must report HasCopiedWrites() == true");
|
||||
|
||||
Require(memory.WritesOverlap(directAddress, 16), "WritesOverlap must return true for direct written region");
|
||||
Require(memory.WritesOverlap(copiedAddress, 16), "WritesOverlap must return true for copied written region");
|
||||
Require(!memory.WritesOverlap(directAddress + 2048, 16), "WritesOverlap must return false for unwritten range");
|
||||
|
||||
Require(!memory.CopiedWritesOverlap(directAddress, 16), "CopiedWritesOverlap must return false for direct written region");
|
||||
Require(memory.CopiedWritesOverlap(copiedAddress, 16), "CopiedWritesOverlap must return true for copied written region");
|
||||
Require(!memory.CopiedWritesOverlap(directAddress + 2048, 16), "CopiedWritesOverlap must return false for unwritten range");
|
||||
|
||||
memory.WriteBack();
|
||||
}
|
||||
|
||||
{
|
||||
RecompileResult shader;
|
||||
shader.runtimeAbiVersion = RuntimeAbi::Version;
|
||||
auto copiedBinding = makeBinding(Role::GuestBuffers, 0, 1, vsharp(copiedBlock, 1024));
|
||||
copiedBinding.bufferWritten = {true};
|
||||
auto directBinding = makeBinding(Role::GuestBuffers, 1, 1, vsharp(directBlock, 1024));
|
||||
directBinding.bufferWritten = {true};
|
||||
shader.bindings = {copiedBinding, directBinding};
|
||||
CompiledShader compiled{ShaderStage::Compute, &shader, 0};
|
||||
auto writer = std::make_shared<ShaderResources>(context, compiled);
|
||||
|
||||
Require(writer->HasCopiedWrites(), "ShaderResources with copied region must report HasCopiedWrites() == true");
|
||||
Require(writer->WritesOverlap(directAddress, 16), "ShaderResources must report WritesOverlap for direct region");
|
||||
Require(!writer->CopiedWritesOverlap(directAddress, 16), "ShaderResources must NOT report CopiedWritesOverlap for direct region");
|
||||
Require(writer->CopiedWritesOverlap(copiedAddress, 16), "ShaderResources must report CopiedWritesOverlap for copied region");
|
||||
|
||||
auto copiedWriters = DrawCopiedWriters();
|
||||
copiedWriters->push_back(writer);
|
||||
|
||||
const auto overlapsMain = [&](const auto& w) { return w->WritesOverlap(directAddress, 16); };
|
||||
const auto overlapsPR = [&](const auto& w) { return w->CopiedWritesOverlap(directAddress, 16); };
|
||||
|
||||
const bool mainOverlaps = std::any_of(copiedWriters->begin(), copiedWriters->end(), overlapsMain);
|
||||
const bool prOverlaps = std::any_of(copiedWriters->begin(), copiedWriters->end(), overlapsPR);
|
||||
|
||||
Require(mainOverlaps, "main's check (WritesOverlap) must flag an overlap over direct arguments");
|
||||
Require(!prOverlaps, "PR's check (CopiedWritesOverlap) must disambiguate and NOT flag an overlap over direct arguments");
|
||||
|
||||
const auto copiedOverlapsPR = [&](const auto& w) { return w->CopiedWritesOverlap(copiedAddress, 16); };
|
||||
Require(std::any_of(copiedWriters->begin(), copiedWriters->end(), copiedOverlapsPR), "PR's check must flag an overlap over copied arguments");
|
||||
|
||||
copiedWriters->erase(std::remove(copiedWriters->begin(), copiedWriters->end(), writer), copiedWriters->end());
|
||||
writer->WriteBack();
|
||||
}
|
||||
|
||||
{
|
||||
auto* mutation = GuestAllocations::GuestAllocationsBegin_nid_postfix();
|
||||
GuestAllocations::GuestAllocationsRemove_nid_postfix(mutation, directBlock);
|
||||
GuestAllocations::GuestAllocationsEnd_nid_postfix(mutation);
|
||||
}
|
||||
::operator delete(directBlock, std::align_val_t{half});
|
||||
::operator delete(copiedBlock, std::align_val_t{half});
|
||||
}
|
||||
|
||||
void rectListTests() {
|
||||
using namespace ShaderRecompiler;
|
||||
using namespace AgcDriver::Graphics;
|
||||
|
|
@ -4642,6 +4736,7 @@ int main(int argc, char** argv) {
|
|||
rectListTests();
|
||||
floatControlsModeTests();
|
||||
barycentricEmulationTests();
|
||||
copiedWriterIndirectOverlapTests();
|
||||
mock = MockVulkan{};
|
||||
auto bdaContext = mockContext();
|
||||
bdaContext.bufferDeviceAddress = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue