#include "BdaShader.hpp" #include "ControlFlow/RequestSerializer.hpp" #include "SpirvBackend/SpirvBda.hpp" #include namespace { template void reject(TAction action, const char* expected) { try { action(); } catch (const std::runtime_error& error) { AgcDriver::Graphics::Require(std::string(error.what()).find(expected) != std::string::npos, std::string("unexpected contract error: ") + error.what()); return; } throw std::runtime_error(std::string("missing contract rejection: ") + expected); } } void RunBdaContractTests() { using namespace ShaderRecompiler; const std::array capabilities{spv::CapabilityInt64, spv::CapabilityPhysicalStorageBufferAddresses, spv::CapabilityStorageBuffer8BitAccess}; const std::array extensions{"SPV_KHR_physical_storage_buffer", "SPV_KHR_8bit_storage"}; SpirvTargetOptions target{0x00401000u, 0x00010300u, 32, BdaAbi::Version, capabilities, extensions}; IrProgram program; program.Resources().stage = IrShaderStage::Compute; program.Info().usesDma = true; ValidateBdaTarget(program, target); target.bdaAbiVersion = 0; reject([&] { ValidateBdaTarget(program, target); }, "ABI version"); target.bdaAbiVersion = BdaAbi::Version; target.supportedCapabilities = {}; reject([&] { ValidateBdaTarget(program, target); }, "capability"); target.supportedCapabilities = capabilities; target.supportedExtensions = {}; reject([&] { ValidateBdaTarget(program, target); }, "extension"); target.supportedExtensions = extensions; auto& block = program.CreateBlock(); block.AppendInstruction(&program.CreateValue(IrOpcode::Barrier, IrType::Void)); program.BlockOrder().push_back(&block); ValidateBdaTarget(program, target); AgcDriver::Graphics::Require(!BdaInvocationsMayStop(program), "a BDA program with barriers must keep its invocations running"); program.Resources().stage = IrShaderStage::TessellationControl; reject([&] { ValidateBdaTarget(program, target); }, "barrier-safe"); program.Resources().stage = IrShaderStage::Compute; RecompileRequest request{}; request.target.bdaAbiVersion = BdaAbi::Version; request.target.supportedCapabilities = capabilities; request.target.supportedExtensions = extensions; request.target.fragmentShaderBarycentricEnabled = false; const RequestSerializer serializer; const auto encoded = serializer.Serialize(request); const auto decoded = serializer.Deserialize(encoded); AgcDriver::Graphics::Require(decoded.request.target.bdaAbiVersion == BdaAbi::Version && decoded.request.target.supportedCapabilities.size() == capabilities.size() && decoded.request.target.supportedExtensions[1] == extensions[1], "BDA request serialization changed target contract"); auto invalid = encoded; invalid[0] = invalid[0] == 'A' ? 'B' : 'A'; reject([&] { static_cast(serializer.Deserialize(invalid)); }, "request signature"); reject([&] { static_cast(serializer.Deserialize("NVNQQWMAAAA=")); }, "serialization version"); }