shader: share runtime value checks

This commit is contained in:
nmzik
2026-09-05 13:16:54 +04:00
parent a379304362
commit ebe0979563
5 changed files with 159 additions and 77 deletions
+50
View File
@@ -159,6 +159,55 @@ void TestMappedSrtUsesDirectReaderByDefault() {
"cache rematerialization did not use the direct reader by default");
}
void TestIntegerRuntimeValueFollowsSrtReads() {
using namespace Libs::Graphics::ShaderRecompiler::IR;
auto plan = SrtPlan(0x10000);
const auto root = plan.descriptor_sources.front().dwords[0];
Check(ValidateRuntimeValue(plan, root, RuntimeValueType::Integer),
"integer SRT read was rejected");
Block values;
auto &comparison = values.AppendNewInst(ValueOpcode::FPOrdLessThanEqual32,
{Value::F32(1.f), Value::F32(0.f)});
auto &selection = values.AppendNewInst(
ValueOpcode::SelectU32, {Value(&comparison), Value(1u), Value(0u)});
plan.srt_reads[0].value = Value(&selection);
Check(ValidateRuntimeValue(plan, root),
"ordinary SRT validation rejected a floating-point dependency");
Check(!ValidateRuntimeValue(plan, root, RuntimeValueType::Integer),
"integer SRT validation missed a hidden floating-point dependency");
auto &first =
values.AppendNewInst(ValueOpcode::ReadFirstLane, {root, Value(true)});
Check(!ValidateRuntimeValue(plan, Value(&first), RuntimeValueType::Integer),
"read-first-lane lost integer-only SRT validation");
auto &active = values.AppendNewInst(ValueOpcode::ReadFirstLane,
{Value(&selection), Value(&comparison)});
Check(!ValidateRuntimeValue(plan, Value(&active), RuntimeValueType::Integer),
"floating-point execution mask was accepted as integer-only");
auto &lane = values.AppendNewInst(
ValueOpcode::GetBuiltin,
{Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)),
Value(0u)});
auto &mask =
values.AppendNewInst(ValueOpcode::INotEqual32, {Value(&lane), Value(0u)});
selection.SetArg(0, Value(&mask));
active.SetArg(1, Value(&mask));
Check(ValidateRuntimeValue(plan, Value(&active), RuntimeValueType::Integer),
"nonuniform integer execution mask was rejected");
auto &float_value =
values.AppendNewInst(ValueOpcode::BitCastU32F32, {Value::F32(1.f)});
selection.SetArg(2, Value(&float_value));
Check(!ValidateRuntimeValue(plan, Value(&active), RuntimeValueType::Integer),
"floating-point inactive arm was accepted as integer-only");
plan.srt_reads[0].value = Value(&first);
Check(!ValidateRuntimeValue(plan, root, RuntimeValueType::Integer),
"cyclic SRT read-first-lane dependency was accepted");
}
void TestUnbasedFlatCacheHitMaterializes() {
using namespace Libs::Graphics::ShaderRecompiler::IR;
auto plan = UnbasedFlatPlan();
@@ -217,6 +266,7 @@ void DbgExit(int) { std::abort(); }
int main() {
TestMappedSrtUsesDirectReaderByDefault();
TestIntegerRuntimeValueFollowsSrtReads();
TestUnbasedFlatCacheHitMaterializes();
TestFailedMaterializationPreservesPriorStage();
TestMixedSamplerDuplicatesTheCorrectSnapshot();
+21 -7
View File
@@ -1681,9 +1681,10 @@ void TestSopkCompareImmediateExtension() {
Decoder::Program decoded;
Decoder::DecodeProgram(shader, decoded);
const auto &operand = decoded.instructions.front().src1;
const int32_t expected = opcode < 0x09
? (immediate == 0x8000u ? -32768 : -1)
: static_cast<int32_t>(immediate);
int32_t expected = static_cast<int32_t>(immediate);
if (opcode < 0x09) {
expected = immediate == 0x8000u ? -32768 : -1;
}
Check(operand.value == static_cast<uint32_t>(expected) &&
operand.signed_val == expected,
"SOPK compare immediate extension does not match its signedness");
@@ -6057,10 +6058,23 @@ void TestMaskedValueDemand() {
{zero, zero, zero, zero, zero, zero, zero, zero});
auto &sampler = entry.AppendNewInst(ValueOpcode::GetSamplerResource,
{zero, zero, zero, zero});
program.memory_info.emplace_back().image_sample_flags =
use == Use::ExplicitLod ? ShaderRecompiler::Decoder::ImageSampleFlagLod :
use == Use::ExplicitGradient ? ShaderRecompiler::Decoder::ImageSampleFlagDerivative :
use == Use::LevelZero ? ShaderRecompiler::Decoder::ImageSampleFlagLevelZero : 0u;
auto &memory = program.memory_info.emplace_back();
switch (use) {
case Use::ExplicitLod:
memory.image_sample_flags =
ShaderRecompiler::Decoder::ImageSampleFlagLod;
break;
case Use::ExplicitGradient:
memory.image_sample_flags =
ShaderRecompiler::Decoder::ImageSampleFlagDerivative;
break;
case Use::LevelZero:
memory.image_sample_flags =
ShaderRecompiler::Decoder::ImageSampleFlagLevelZero;
break;
default:
break;
}
value = Value(&join.AppendNewInst(ValueOpcode::ImageSampleRaw,
{Value(&image), Value(&sampler), Value(&address)}));
value = Value(&join.AppendNewInst(ValueOpcode::CompositeExtractU32x4, {value, Value(0u)}));