mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
shader: remove second IR layer
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/BindingLayout.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/DeadCodeElimination.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/ResourceMaterialization.h"
|
||||
@@ -35,7 +35,6 @@ struct Fixture {
|
||||
|
||||
explicit Fixture(ShaderType stage = ShaderType::Compute) {
|
||||
program.stage = stage;
|
||||
program.values = std::make_shared<ValueProgram>();
|
||||
program.user_data_count = 64;
|
||||
block = AddBlock();
|
||||
}
|
||||
@@ -43,10 +42,10 @@ struct Fixture {
|
||||
Block *AddBlock() {
|
||||
auto storage = std::make_unique<Block>();
|
||||
auto *result = storage.get();
|
||||
program.values->block_storage.push_back(std::move(storage));
|
||||
program.values->blocks.push_back(result);
|
||||
program.values->block_info.push_back(
|
||||
{.id = static_cast<uint32_t>(program.values->block_info.size())});
|
||||
program.block_storage.push_back(std::move(storage));
|
||||
program.blocks.push_back(result);
|
||||
program.block_info.push_back(
|
||||
{.id = static_cast<uint32_t>(program.block_info.size())});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -77,8 +76,8 @@ struct Fixture {
|
||||
|
||||
MemoryFlags AddMemory(MemoryInfo memory, uint32_t pc) {
|
||||
const auto index =
|
||||
static_cast<uint32_t>(program.values->memory_info.size());
|
||||
program.values->memory_info.push_back(memory);
|
||||
static_cast<uint32_t>(program.memory_info.size());
|
||||
program.memory_info.push_back(memory);
|
||||
return {index, pc};
|
||||
}
|
||||
|
||||
@@ -241,19 +240,19 @@ MakeIndirectImageFixture(bool malformed, uint32_t material_immediate = 0,
|
||||
void TestInvariantIndirectImageMaterialization() {
|
||||
auto fixture = MakeIndirectImageFixture(false);
|
||||
fixture->PlanAndTrack();
|
||||
EliminateDeadCode(fixture->program.values->blocks);
|
||||
EliminateDeadCode(fixture->program.blocks);
|
||||
std::string validation_error;
|
||||
Check(
|
||||
ValidateValueProgram(*fixture->program.values, true, &validation_error),
|
||||
ValidateProgram(fixture->program, true, &validation_error),
|
||||
"post-tracking dead-code elimination invalidated descriptor provenance");
|
||||
|
||||
Check(fixture->program.info.buffers.size() == 1 &&
|
||||
fixture->program.info.images.size() == 1 &&
|
||||
fixture->program.values->dynamic_reads.size() == 1,
|
||||
fixture->program.dynamic_reads.size() == 1,
|
||||
"indirect image key was not retained as a scalar-buffer read");
|
||||
const auto source = fixture->program.info.images[0].source;
|
||||
Check(source < fixture->program.values->descriptor_sources.size() &&
|
||||
fixture->program.values->descriptor_sources[source]
|
||||
Check(source < fixture->program.descriptor_sources.size() &&
|
||||
fixture->program.descriptor_sources[source]
|
||||
.indirect_image.has_value(),
|
||||
"indirect image source was not retained for runtime proof");
|
||||
const auto image_handle =
|
||||
@@ -407,7 +406,7 @@ void TestInvariantIndirectImageMaterialization() {
|
||||
|
||||
auto memory_backed = MakeIndirectImageFixture(false, 0u, true);
|
||||
memory_backed->PlanAndTrack();
|
||||
EliminateDeadCode(memory_backed->program.values->blocks);
|
||||
EliminateDeadCode(memory_backed->program.blocks);
|
||||
std::array<uint32_t, 11> memory_backed_user_data{0x1000u, 224u << 16u, 2u, 0u,
|
||||
0x2000u, 16u << 16u, 4u, 0u,
|
||||
7u, 0x3100u, 0u};
|
||||
@@ -431,7 +430,7 @@ void TestInvariantIndirectImageMaterialization() {
|
||||
error.find("ReadFirstLane") != std::string::npos &&
|
||||
!malformed->program.resource_tracking_complete &&
|
||||
malformed->program.info.images.empty() &&
|
||||
malformed->program.values->descriptor_sources.empty(),
|
||||
malformed->program.descriptor_sources.empty(),
|
||||
"malformed indirect image pattern was partially accepted");
|
||||
|
||||
auto wrapped_immediate = MakeIndirectImageFixture(false, 4u);
|
||||
@@ -484,7 +483,7 @@ void TestDenseBufferTracking() {
|
||||
|
||||
Check(fixture.program.info.buffers.size() == 2,
|
||||
"typed buffer sources were not densely interned");
|
||||
Check(fixture.program.values->descriptor_sources.size() == 2,
|
||||
Check(fixture.program.descriptor_sources.size() == 2,
|
||||
"descriptor source table did not match dense topology");
|
||||
const auto &resource = fixture.program.info.buffers[0];
|
||||
Check(resource.read && resource.written && resource.atomic &&
|
||||
@@ -494,10 +493,10 @@ void TestDenseBufferTracking() {
|
||||
Check(first.Instruction()->Flags<uint32_t>() == 0 &&
|
||||
second.Instruction()->Flags<uint32_t>() == 1,
|
||||
"typed handles were not assigned dense indices");
|
||||
Check(fixture.program.values->memory_info[load_flags.index].resource == 0 &&
|
||||
fixture.program.values->memory_info[store_flags.index].resource ==
|
||||
Check(fixture.program.memory_info[load_flags.index].resource == 0 &&
|
||||
fixture.program.memory_info[store_flags.index].resource ==
|
||||
0 &&
|
||||
fixture.program.values->memory_info[other_flags.index].resource ==
|
||||
fixture.program.memory_info[other_flags.index].resource ==
|
||||
1,
|
||||
"typed memory metadata was not patched to dense indices");
|
||||
|
||||
@@ -531,8 +530,8 @@ void TestScalarAndVectorBufferAlias() {
|
||||
Check(fixture.program.info.buffers.size() == 1 &&
|
||||
fixture.program.info.buffers[0].scalar,
|
||||
"typed scalar and vector uses of one descriptor were split");
|
||||
Check(fixture.program.values->memory_info[scalar_flags.index].resource == 0 &&
|
||||
fixture.program.values->memory_info[vector_flags.index].resource ==
|
||||
Check(fixture.program.memory_info[scalar_flags.index].resource == 0 &&
|
||||
fixture.program.memory_info[vector_flags.index].resource ==
|
||||
0,
|
||||
"scalar/vector alias did not share a dense index");
|
||||
}
|
||||
@@ -625,7 +624,7 @@ void TestImagesSamplersAndAliases() {
|
||||
repeated.second.Instruction()->Flags<uint32_t>() == 0,
|
||||
"unused sampler border colors prevented source interning");
|
||||
const auto sampler_source = fixture.program.info.samplers[0].source;
|
||||
Check(fixture.program.values->descriptor_sources[sampler_source]
|
||||
Check(fixture.program.descriptor_sources[sampler_source]
|
||||
.dwords[3]
|
||||
.U32() == 0,
|
||||
"unused sampler border color was not canonicalized");
|
||||
@@ -665,7 +664,7 @@ void TestSampleAdjustSamplerScratch() {
|
||||
fixture.PlanAndTrack();
|
||||
|
||||
const auto source = fixture.program.info.samplers[0].source;
|
||||
const auto stored = fixture.program.values->descriptor_sources[source]
|
||||
const auto stored = fixture.program.descriptor_sources[source]
|
||||
.dwords[3]
|
||||
.Resolve()
|
||||
.TryInstruction();
|
||||
@@ -758,10 +757,10 @@ void TestDynamicStorageMipTracking() {
|
||||
mip1.first.Instruction()->Flags<uint32_t>() == 1 &&
|
||||
mip2.first.Instruction()->Flags<uint32_t>() == 1 &&
|
||||
dynamic.first.Instruction()->Flags<uint32_t>() == 1 &&
|
||||
fixture.program.values->memory_info[plain.second].resource == 0 &&
|
||||
fixture.program.values->memory_info[mip1.second].resource == 1 &&
|
||||
fixture.program.values->memory_info[mip2.second].resource == 1 &&
|
||||
fixture.program.values->memory_info[dynamic.second].resource == 1,
|
||||
fixture.program.memory_info[plain.second].resource == 0 &&
|
||||
fixture.program.memory_info[mip1.second].resource == 1 &&
|
||||
fixture.program.memory_info[mip2.second].resource == 1 &&
|
||||
fixture.program.memory_info[dynamic.second].resource == 1,
|
||||
"dynamic storage mip handles and memory metadata were not patched");
|
||||
|
||||
DescriptorValue descriptor{};
|
||||
@@ -795,7 +794,6 @@ void TestDynamicStorageMipTracking() {
|
||||
"dynamic storage mip descriptors were not expanded consecutively");
|
||||
|
||||
Program null_program;
|
||||
null_program.values = std::make_shared<ValueProgram>();
|
||||
null_program.resource_tracking_complete = true;
|
||||
ImageResource null_image;
|
||||
null_image.kind = ResourceKind::StorageImage;
|
||||
@@ -847,12 +845,12 @@ void TestSrtFlatteningAndRuntimeMemoization() {
|
||||
fixture.AddMemory(buffer, 16));
|
||||
fixture.PlanAndTrack();
|
||||
|
||||
Check(fixture.program.values->srt_reads.size() == 1,
|
||||
Check(fixture.program.srt_reads.size() == 1,
|
||||
"shared typed scalar read did not receive one flat SRT slot");
|
||||
Check(fixture.program.info.buffers.size() == 1 &&
|
||||
fixture.program.info.addresses.empty(),
|
||||
"planning-only scalar reads leaked into resource topology");
|
||||
Check(fixture.program.values->memory_info[0].planning_only,
|
||||
Check(fixture.program.memory_info[0].planning_only,
|
||||
"canonical runtime scalar read was not marked planning-only");
|
||||
|
||||
std::array<uint32_t, 2> user_data{0x1000u, 0u};
|
||||
@@ -910,8 +908,8 @@ void TestDynamicSrtReadRemainsExplicit() {
|
||||
fixture.AddMemory(buffer, 8));
|
||||
fixture.PlanAndTrack();
|
||||
|
||||
Check(fixture.program.values->srt_reads.empty() &&
|
||||
fixture.program.values->dynamic_reads.size() == 1 &&
|
||||
Check(fixture.program.srt_reads.empty() &&
|
||||
fixture.program.dynamic_reads.size() == 1 &&
|
||||
fixture.program.info.addresses.size() == 1,
|
||||
"dynamic scalar read was incorrectly flattened or lost");
|
||||
std::array<uint32_t, 3> user_data{0x1000u, 0u, 4u};
|
||||
@@ -973,7 +971,7 @@ void TestPhiValidation() {
|
||||
error.find("control-dependent phi") != std::string::npos &&
|
||||
!fixture.program.resource_tracking_complete &&
|
||||
fixture.program.info.buffers.empty() &&
|
||||
fixture.program.values->descriptor_sources.empty(),
|
||||
fixture.program.descriptor_sources.empty(),
|
||||
"control-dependent descriptor phi was not rejected transactionally");
|
||||
}
|
||||
|
||||
@@ -1295,7 +1293,7 @@ void TestResourceLimitIsTransactional() {
|
||||
error.find("buffer resource limit exceeded") != std::string::npos &&
|
||||
!fixture.program.resource_tracking_complete &&
|
||||
fixture.program.info.buffers.empty() &&
|
||||
fixture.program.values->descriptor_sources.empty(),
|
||||
fixture.program.descriptor_sources.empty(),
|
||||
"resource-limit failure partially mutated typed resource state");
|
||||
}
|
||||
|
||||
@@ -1412,13 +1410,18 @@ int main() {
|
||||
|
||||
// The full emulator supplies these assertion hooks through common. This focused
|
||||
// target links only fmt; keep assertion failures observable without widening
|
||||
// its legacy build manifest.
|
||||
// its focused build manifest.
|
||||
namespace Common {
|
||||
int DbgExitIfHandler(const char *expression, const char *file, int line) {
|
||||
throw std::runtime_error(std::string("typed IR assertion: ") + expression +
|
||||
" at " + file + ':' + std::to_string(line));
|
||||
}
|
||||
|
||||
int DbgNotImplementedHandler(const char *expression, const char *file, int line) {
|
||||
throw std::runtime_error(std::string("typed IR not implemented: ") + expression +
|
||||
" at " + file + ':' + std::to_string(line));
|
||||
}
|
||||
|
||||
void DbgExit(int) { throw std::runtime_error("typed IR assertion failed"); }
|
||||
} // namespace Common
|
||||
|
||||
@@ -1427,6 +1430,6 @@ void DbgExit(int) { throw std::runtime_error("typed IR assertion failed"); }
|
||||
#include "graphics/shader/recompiler/ir/Block.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Type.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Value.cpp"
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Program.cpp"
|
||||
#include "graphics/shader/recompiler/ir/opcodes/ValueOpcodes.cpp"
|
||||
#include "graphics/shader/recompiler/ir/passes/DeadCodeElimination.cpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/ConstantPropagation.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/DeadCodeElimination.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/ReadLaneElimination.h"
|
||||
@@ -27,16 +27,15 @@ struct Fixture {
|
||||
program.stage = ShaderType::Compute;
|
||||
program.shader_hash = 0x12345678u;
|
||||
program.user_data_base = 2;
|
||||
program.values = std::make_shared<ValueProgram>();
|
||||
for (uint32_t index = 0; index < block_count; index++) {
|
||||
program.values->block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.values->block_storage.back().get();
|
||||
program.values->blocks.push_back(block);
|
||||
program.values->block_info.push_back({.id = index});
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = index});
|
||||
}
|
||||
}
|
||||
|
||||
Block &BlockAt(uint32_t index = 0) { return *program.values->blocks[index]; }
|
||||
Block &BlockAt(uint32_t index = 0) { return *program.blocks[index]; }
|
||||
|
||||
Value Emit(ValueOpcode opcode, std::initializer_list<Value> args = {},
|
||||
uint64_t flags = 0, uint32_t block = 0) {
|
||||
@@ -55,8 +54,8 @@ struct Fixture {
|
||||
MemoryInfo info;
|
||||
info.kind = kind;
|
||||
info.offset = static_cast<uint32_t>(offset);
|
||||
program.values->memory_info.push_back(info);
|
||||
return static_cast<uint32_t>(program.values->memory_info.size() - 1u);
|
||||
program.memory_info.push_back(info);
|
||||
return static_cast<uint32_t>(program.memory_info.size() - 1u);
|
||||
}
|
||||
|
||||
void Plan() {
|
||||
@@ -103,11 +102,11 @@ void TestImmediateFlatteningAndGvn() {
|
||||
{first, second, Value(16u), Value(0u)});
|
||||
|
||||
fixture.Plan();
|
||||
Check(fixture.program.values->srt_reads.size() == 1,
|
||||
Check(fixture.program.srt_reads.size() == 1,
|
||||
"equivalent typed scalar reads were not coalesced");
|
||||
Check(fixture.program.values->dynamic_reads.empty(),
|
||||
Check(fixture.program.dynamic_reads.empty(),
|
||||
"immediate scalar read was classified as dynamic");
|
||||
Check(fixture.program.values->memory_info[memory].planning_only,
|
||||
Check(fixture.program.memory_info[memory].planning_only,
|
||||
"flattened raw read was not kept as a planning-only root");
|
||||
|
||||
TestMemory memory_image{{{0x1020u, 0xfeedbeefu}}};
|
||||
@@ -173,8 +172,8 @@ void TestDynamicReadRemainsTyped() {
|
||||
{read, Value(0u), Value(16u), Value(0u)});
|
||||
|
||||
fixture.Plan();
|
||||
Check(fixture.program.values->srt_reads.empty() &&
|
||||
fixture.program.values->dynamic_reads == std::vector<Value>{read},
|
||||
Check(fixture.program.srt_reads.empty() &&
|
||||
fixture.program.dynamic_reads == std::vector<Value>{read},
|
||||
"dynamic scalar read received a fake flattened slot");
|
||||
}
|
||||
|
||||
@@ -209,7 +208,7 @@ void TestShaderBaseAndUserData() {
|
||||
{Value(static_cast<ScalarReg>(2))});
|
||||
const auto sum = fixture.Emit(ValueOpcode::IAdd32, {user, Value(4u)});
|
||||
fixture.Plan();
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {low, high, sum}, .dword_count = 3});
|
||||
|
||||
const std::array user_data{0x20u};
|
||||
@@ -239,7 +238,7 @@ void TestCarryAndBitFields() {
|
||||
const auto sign = fixture.Emit(ValueOpcode::BitFieldSExtract,
|
||||
{Value(0x000000f0u), Value(4u), Value(4u)});
|
||||
fixture.Plan();
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {low, high, inserted, sign}, .dword_count = 4});
|
||||
|
||||
DescriptorValue result;
|
||||
@@ -262,9 +261,9 @@ void TestInvariantAndDivergentPhi() {
|
||||
divergent.AddPhiOperand(&fixture.BlockAt(0), Value(7u));
|
||||
divergent.AddPhiOperand(&fixture.BlockAt(1), Value(9u));
|
||||
fixture.Plan();
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {Value(&invariant)}, .dword_count = 1});
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {Value(&divergent)}, .dword_count = 1});
|
||||
|
||||
DescriptorValue result;
|
||||
@@ -293,10 +292,10 @@ void TestControlDependentStandaloneLoadStaysTyped() {
|
||||
RawRead(fixture, Address(fixture, Value(&base), Value(0u), 2), Value(0u),
|
||||
memory, 2);
|
||||
fixture.Plan();
|
||||
Check(fixture.program.values->srt_reads.empty() &&
|
||||
Check(fixture.program.srt_reads.empty() &&
|
||||
read.ResolveInstruction()->GetOpcode() ==
|
||||
ValueOpcode::LoadAddressU32 &&
|
||||
!fixture.program.values->memory_info[memory].planning_only,
|
||||
!fixture.program.memory_info[memory].planning_only,
|
||||
"control-dependent standalone scalar load was flattened into a host "
|
||||
"snapshot");
|
||||
}
|
||||
@@ -315,7 +314,7 @@ void TestRuntime64BitDescriptorOps() {
|
||||
const auto high =
|
||||
fixture.Emit(ValueOpcode::CompositeExtractU64, {combined, Value(1u)});
|
||||
fixture.Plan();
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {low, high}, .dword_count = 2});
|
||||
|
||||
DescriptorValue result;
|
||||
@@ -370,7 +369,7 @@ void TestReadLaneElimination() {
|
||||
{undef, Value(0xdeadbeefu), Value(5u)});
|
||||
const auto read = fixture.Emit(ValueOpcode::ReadLane, {write, Value(5u)});
|
||||
const auto use = fixture.Emit(ValueOpcode::IAdd32, {read, Value(1u)});
|
||||
const auto stats = EliminateReadLane(*fixture.program.values, 64);
|
||||
const auto stats = EliminateReadLane(fixture.program, 64);
|
||||
Check(stats.rewritten_reads == 1 &&
|
||||
use.ResolveInstruction()->Arg(0).Resolve() == Value(0xdeadbeefu),
|
||||
"fixed-lane typed read was not rewritten from its SSA write chain");
|
||||
@@ -379,7 +378,7 @@ void TestReadLaneElimination() {
|
||||
{Value(static_cast<ScalarReg>(2))});
|
||||
const auto dynamic = fixture.Emit(ValueOpcode::ReadLane, {write, selector});
|
||||
fixture.Emit(ValueOpcode::IAdd32, {dynamic, Value(1u)});
|
||||
Check(EliminateReadLane(*fixture.program.values, 64).rewritten_reads == 0,
|
||||
Check(EliminateReadLane(fixture.program, 64).rewritten_reads == 0,
|
||||
"dynamic-lane read was rewritten unsafely");
|
||||
}
|
||||
|
||||
@@ -390,9 +389,9 @@ void TestOptimizationPipeline() {
|
||||
fixture.Emit(ValueOpcode::ReferenceU32, {kept});
|
||||
fixture.Emit(ValueOpcode::IMul32, {Value(6u), Value(7u)});
|
||||
|
||||
ConstantPropagationPass(fixture.program.values->blocks);
|
||||
RemoveIdentities(fixture.program.values->blocks);
|
||||
EliminateDeadCode(fixture.program.values->blocks);
|
||||
ConstantPropagationPass(fixture.program.blocks);
|
||||
RemoveIdentities(fixture.program.blocks);
|
||||
EliminateDeadCode(fixture.program.blocks);
|
||||
|
||||
const auto &instructions = fixture.BlockAt().Instructions();
|
||||
Check(instructions.size() == 1 &&
|
||||
@@ -404,20 +403,20 @@ void TestOptimizationPipeline() {
|
||||
|
||||
void TestControlFlowValueSurvivesReadLaneFolding() {
|
||||
Fixture fixture(3);
|
||||
auto *entry = fixture.program.values->blocks[0];
|
||||
auto *taken = fixture.program.values->blocks[1];
|
||||
auto *other = fixture.program.values->blocks[2];
|
||||
auto *entry = fixture.program.blocks[0];
|
||||
auto *taken = fixture.program.blocks[1];
|
||||
auto *other = fixture.program.blocks[2];
|
||||
entry->AddBranch(taken);
|
||||
entry->AddBranch(other);
|
||||
|
||||
auto &entry_info = fixture.program.values->block_info[0];
|
||||
auto &entry_info = fixture.program.block_info[0];
|
||||
entry_info.terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::ConditionalBranch;
|
||||
entry_info.terminator.true_block = 1;
|
||||
entry_info.terminator.false_block = 2;
|
||||
fixture.program.values->block_info[1].terminator.kind =
|
||||
fixture.program.block_info[1].terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
fixture.program.values->block_info[2].terminator.kind =
|
||||
fixture.program.block_info[2].terminator.kind =
|
||||
Libs::Graphics::ShaderRecompiler::CFG::TerminatorKind::Return;
|
||||
|
||||
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
||||
@@ -429,16 +428,16 @@ void TestControlFlowValueSurvivesReadLaneFolding() {
|
||||
fixture.Emit(ValueOpcode::IEqual32, {read, Value(42u)});
|
||||
fixture.Emit(ValueOpcode::Reference, {entry_info.condition});
|
||||
|
||||
Check(EliminateReadLane(*fixture.program.values, 64).rewritten_reads == 1,
|
||||
Check(EliminateReadLane(fixture.program, 64).rewritten_reads == 1,
|
||||
"control-flow fixture did not eliminate its fixed-lane read");
|
||||
ConstantPropagationPass(fixture.program.values->blocks);
|
||||
ResolveControlFlowIdentities(*fixture.program.values);
|
||||
RemoveIdentities(fixture.program.values->blocks);
|
||||
EliminateDeadCode(fixture.program.values->blocks);
|
||||
ConstantPropagationPass(fixture.program.blocks);
|
||||
ResolveControlFlowIdentities(fixture.program);
|
||||
RemoveIdentities(fixture.program.blocks);
|
||||
EliminateDeadCode(fixture.program.blocks);
|
||||
|
||||
std::string error;
|
||||
Check(entry_info.condition == Value(true) &&
|
||||
ValidateValueProgram(*fixture.program.values, true, &error),
|
||||
ValidateProgram(fixture.program, true, &error),
|
||||
error.empty() ? "folded branch condition did not survive identity removal"
|
||||
: error.c_str());
|
||||
}
|
||||
@@ -447,7 +446,7 @@ void TestUndefinedRuntimeValueFails() {
|
||||
Fixture fixture;
|
||||
const auto undef = fixture.Emit(ValueOpcode::UndefU32);
|
||||
fixture.Plan();
|
||||
fixture.program.values->descriptor_sources.push_back(
|
||||
fixture.program.descriptor_sources.push_back(
|
||||
{.dwords = {undef}, .dword_count = 1});
|
||||
DescriptorValue result;
|
||||
result.dword_count = 3;
|
||||
@@ -499,7 +498,7 @@ int main() {
|
||||
#include "../src/graphics/shader/recompiler/ir/Block.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/Type.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/Value.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/ValueProgram.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/Program.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/opcodes/ValueOpcodes.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/passes/ConstantPropagation.cpp"
|
||||
#include "../src/graphics/shader/recompiler/ir/passes/DeadCodeElimination.cpp"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "graphics/shader/recompiler/backend/spirv/SpirvBuilder.h"
|
||||
#include "graphics/shader/recompiler/backend/spirv/SpirvEmitter.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/BindingLayout.h"
|
||||
#include "graphics/shader/rectListShader.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
@@ -967,7 +967,6 @@ struct TestCase {
|
||||
std::vector<u32> expected_gds;
|
||||
std::vector<std::pair<std::string, size_t>> decoded_counts;
|
||||
std::vector<std::pair<std::string, size_t>> ir_counts;
|
||||
std::vector<std::pair<std::string, size_t>> native_ir_counts;
|
||||
u32 expected_storage_mip_descriptors = 0;
|
||||
};
|
||||
|
||||
@@ -1192,32 +1191,6 @@ CompiledShader CompileCase(const TestCase &test) {
|
||||
text + " count=" + std::to_string(actual) +
|
||||
", expected=" + std::to_string(expected));
|
||||
}
|
||||
if (!test.native_ir_counts.empty()) {
|
||||
ShaderRecompiler::Decoder::Program decoded;
|
||||
ShaderRecompiler::CFG::Graph cfg;
|
||||
ShaderRecompiler::IR::Program native;
|
||||
std::string native_error;
|
||||
Require(test.name, "native decode",
|
||||
ShaderRecompiler::Decoder::DecodeProgram(test.code, decoded,
|
||||
&native_error),
|
||||
native_error);
|
||||
Require(test.name, "native CFG",
|
||||
ShaderRecompiler::CFG::BuildGraph(decoded, cfg, &native_error) &&
|
||||
ShaderRecompiler::CFG::Structurize(cfg, &native_error),
|
||||
native_error);
|
||||
Require(test.name, "native lowering",
|
||||
ShaderRecompiler::IR::LowerProgram(decoded, cfg, options.stage,
|
||||
options.wave_size, native,
|
||||
&native_error),
|
||||
native_error);
|
||||
const auto native_ir = ShaderRecompiler::IR::ProgramToString(native);
|
||||
for (const auto &[text, expected] : test.native_ir_counts) {
|
||||
const auto actual = CountText(native_ir, text);
|
||||
Require(test.name, "native IR", actual == expected,
|
||||
text + " count=" + std::to_string(actual) +
|
||||
", expected=" + std::to_string(expected));
|
||||
}
|
||||
}
|
||||
if (test.expected_storage_mip_descriptors != 0) {
|
||||
const auto image = std::ranges::find_if(
|
||||
result.program.info.images, [](const auto &resource) {
|
||||
@@ -1242,7 +1215,7 @@ CompiledShader CompileCase(const TestCase &test) {
|
||||
"dynamic storage image did not receive one descriptor per mip");
|
||||
}
|
||||
if (test.expand_shader_data_storage) {
|
||||
auto &block = *result.program.values->blocks.front();
|
||||
auto &block = *result.program.blocks.front();
|
||||
for (u32 reg = 0; reg < 33; reg++) {
|
||||
auto &user_data = block.AppendNewInst(
|
||||
ShaderRecompiler::IR::ValueOpcode::GetUserData,
|
||||
@@ -7519,8 +7492,6 @@ public:
|
||||
|
||||
ShaderRecompiler::IR::Program null_program{};
|
||||
null_program.stage = ShaderType::Compute;
|
||||
null_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
null_program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource null_resource{};
|
||||
null_resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||
@@ -7630,8 +7601,6 @@ public:
|
||||
storage.fields[5] = 0x00700000u;
|
||||
ShaderRecompiler::IR::Program storage_program{};
|
||||
storage_program.stage = ShaderType::Vertex;
|
||||
storage_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
storage_program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource storage_resource{};
|
||||
storage_resource.kind =
|
||||
@@ -7911,8 +7880,6 @@ public:
|
||||
|
||||
ShaderRecompiler::IR::Program sampled_program{};
|
||||
sampled_program.stage = ShaderType::Pixel;
|
||||
sampled_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
sampled_program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource sampled_resource{};
|
||||
sampled_resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||
@@ -8003,15 +7970,19 @@ public:
|
||||
RenderExecutorTestAccess::ResetBindings(executor);
|
||||
|
||||
auto vertex_sampled_program =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>(
|
||||
*sampled_runtime.program);
|
||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
vertex_sampled_program->stage = ShaderType::Vertex;
|
||||
vertex_sampled_program->resource_tracking_complete = true;
|
||||
vertex_sampled_program->info.images.push_back(sampled_resource);
|
||||
allocate_bindings(*vertex_sampled_program);
|
||||
ShaderStageRuntime vertex_sampled_runtime{
|
||||
std::move(vertex_sampled_program), sampled_runtime.resources};
|
||||
auto pixel_storage_program =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>(
|
||||
*storage_runtime.program);
|
||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
pixel_storage_program->stage = ShaderType::Pixel;
|
||||
pixel_storage_program->resource_tracking_complete = true;
|
||||
pixel_storage_program->info.images.push_back(storage_resource);
|
||||
allocate_bindings(*pixel_storage_program);
|
||||
ShaderStageRuntime pixel_storage_runtime{std::move(pixel_storage_program),
|
||||
storage_runtime.resources};
|
||||
auto writable_alias_bindings =
|
||||
@@ -8083,8 +8054,6 @@ public:
|
||||
|
||||
auto split_program = std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
split_program->stage = ShaderType::Vertex;
|
||||
split_program->values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
split_program->resource_tracking_complete = true;
|
||||
split_program->info.images = {storage_resource, sampled_resource};
|
||||
allocate_bindings(*split_program);
|
||||
@@ -8459,8 +8428,6 @@ public:
|
||||
|
||||
ShaderRecompiler::IR::Program array_program{};
|
||||
array_program.stage = ShaderType::Compute;
|
||||
array_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
array_program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource array_resource{};
|
||||
array_resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||
@@ -8544,10 +8511,13 @@ public:
|
||||
colliding_msaa_descriptor.dwords.begin());
|
||||
colliding_msaa_descriptor.dword_count = 8;
|
||||
auto colliding_msaa_program =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>(
|
||||
*array_runtime.program);
|
||||
colliding_msaa_program->info.images[0].dimension =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
colliding_msaa_program->stage = ShaderType::Compute;
|
||||
colliding_msaa_program->resource_tracking_complete = true;
|
||||
auto colliding_msaa_resource = array_resource;
|
||||
colliding_msaa_resource.dimension =
|
||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa;
|
||||
colliding_msaa_program->info.images.push_back(colliding_msaa_resource);
|
||||
auto colliding_msaa_snapshot =
|
||||
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
colliding_msaa_snapshot->images.push_back(colliding_msaa_descriptor);
|
||||
@@ -8604,10 +8574,13 @@ public:
|
||||
std::copy(std::begin(msaa_texture.fields), std::end(msaa_texture.fields),
|
||||
msaa_descriptor.dwords.begin());
|
||||
msaa_descriptor.dword_count = 8;
|
||||
auto msaa_program = std::make_shared<ShaderRecompiler::IR::Program>(
|
||||
*array_runtime.program);
|
||||
msaa_program->info.images[0].dimension =
|
||||
auto msaa_program = std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
msaa_program->stage = ShaderType::Compute;
|
||||
msaa_program->resource_tracking_complete = true;
|
||||
auto msaa_resource = array_resource;
|
||||
msaa_resource.dimension =
|
||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaa;
|
||||
msaa_program->info.images.push_back(msaa_resource);
|
||||
auto msaa_snapshot =
|
||||
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
msaa_snapshot->images.push_back(msaa_descriptor);
|
||||
@@ -8643,10 +8616,14 @@ public:
|
||||
std::end(msaa_array_texture.fields),
|
||||
msaa_array_descriptor.dwords.begin());
|
||||
msaa_array_descriptor.dword_count = 8;
|
||||
auto msaa_array_program = std::make_shared<ShaderRecompiler::IR::Program>(
|
||||
*msaa_runtime.program);
|
||||
msaa_array_program->info.images[0].dimension =
|
||||
auto msaa_array_program =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
msaa_array_program->stage = ShaderType::Compute;
|
||||
msaa_array_program->resource_tracking_complete = true;
|
||||
auto msaa_array_resource = array_resource;
|
||||
msaa_array_resource.dimension =
|
||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DMsaaArray;
|
||||
msaa_array_program->info.images.push_back(msaa_array_resource);
|
||||
auto msaa_array_snapshot =
|
||||
std::make_shared<ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
msaa_array_snapshot->images.push_back(msaa_array_descriptor);
|
||||
@@ -8868,7 +8845,6 @@ public:
|
||||
|
||||
ShaderRecompiler::IR::Program program{};
|
||||
program.stage = ShaderType::Compute;
|
||||
program.values = std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource stencil_resource{};
|
||||
stencil_resource.kind = ShaderRecompiler::IR::ResourceKind::ImageUint;
|
||||
@@ -8940,11 +8916,15 @@ public:
|
||||
RenderExecutorTestAccess::ResetBindings(executor);
|
||||
|
||||
auto stencil_storage_program =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>(*runtime.program);
|
||||
stencil_storage_program->info.images[0].kind =
|
||||
std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
stencil_storage_program->stage = ShaderType::Compute;
|
||||
stencil_storage_program->resource_tracking_complete = true;
|
||||
auto stencil_storage_resource = stencil_resource;
|
||||
stencil_storage_resource.kind =
|
||||
ShaderRecompiler::IR::ResourceKind::StorageImageUint;
|
||||
stencil_storage_program->info.images[0].read = false;
|
||||
stencil_storage_program->info.images[0].written = true;
|
||||
stencil_storage_resource.read = false;
|
||||
stencil_storage_resource.written = true;
|
||||
stencil_storage_program->info.images.push_back(stencil_storage_resource);
|
||||
auto storage_stencil = stencil;
|
||||
storage_stencil.fields[5] = 0x00700000u;
|
||||
ShaderRecompiler::IR::DescriptorValue stencil_storage_descriptor{};
|
||||
@@ -12132,7 +12112,6 @@ TestCase ScalarWaitcntDepctrCapturedVmVsrc() {
|
||||
test.opcodes = {O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_WAITCNT_DEPCTR,
|
||||
O::S_ENDPGM};
|
||||
test.decoded_counts = {{"0x00000010: S_WAITCNT_DEPCTR 0x0000ffe3\n", 1}};
|
||||
test.native_ir_counts = {{"0x00000010: Waitcnt null, 0x0000ffe3", 1}};
|
||||
test.forbidden_spirv = {"OpControlBarrier", "OpMemoryBarrier"};
|
||||
return test;
|
||||
}
|
||||
@@ -13289,7 +13268,6 @@ TestCase Vop3Med3I16Captured() {
|
||||
test.decoded_counts = {{"0x00000020: V_MED3_I16 v3.sdwa(sel=5,sext=0), "
|
||||
"v5.opsel(lo=1,hi=0,neghi=0), s25, s27\n",
|
||||
1}};
|
||||
test.native_ir_counts = {{"IMed3I16", 1}};
|
||||
test.required_spirv = {"OpSLessThan"};
|
||||
return test;
|
||||
}
|
||||
@@ -15227,8 +15205,6 @@ TestCase VectorVopcCmpxNeU64CapturedExecMask() {
|
||||
O::S_MOV_B32, O::S_ENDPGM}};
|
||||
test.decoded_counts = {{"V_CMPX_NE_U64 exec_lo, 0, v7", 2},
|
||||
{"V_CMPX_NE_U64 exec_lo, 0, v2", 2}};
|
||||
test.native_ir_counts = {{"CompareNeU64 exec_lo, 0x00000000, v7", 2},
|
||||
{"CompareNeU64 exec_lo, 0x00000000, v2", 2}};
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -15258,7 +15234,6 @@ TestCase VectorVop3CmpxNeI64CapturedExecMask() {
|
||||
{O::V_MOV_B32, O::V_CMPX_NE_I64, O::BUFFER_STORE_DWORD,
|
||||
O::S_MOV_B32, O::S_ENDPGM}};
|
||||
test.decoded_counts = {{"V_CMPX_NE_I64 exec_lo, 0, v7", 2}};
|
||||
test.native_ir_counts = {{"CompareNeU64 exec_lo, 0x00000000, v7", 2}};
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -17738,7 +17713,6 @@ TestCase DsReadU16D16CapturedPreservesHighHalf() {
|
||||
{O::V_MOV_B32, O::DS_WRITE_B32, O::DS_READ_U16_D16,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
test.decoded_counts = {{"DS_READ_U16_D16", 2}};
|
||||
test.native_ir_counts = {{"DsReadUshort", 2}};
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -18652,7 +18626,6 @@ TestCase ImageLoadR128IgnoresAdjacentMaskSgprs() {
|
||||
test.user_data = MakeSampledTextureData(Prospero::BufferFormat::k32UInt);
|
||||
test.has_user_data = true;
|
||||
test.decoded_counts = {{"r128=1", 1}};
|
||||
test.native_ir_counts = {{"image_r128=1", 1}};
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -18974,8 +18947,6 @@ TestCase ImageD16GatherPacksHalfPairs() {
|
||||
O::S_ENDPGM};
|
||||
test.sampled_image_rgba = image;
|
||||
test.decoded_counts = {{"d16=1", 1}};
|
||||
test.native_ir_counts = {
|
||||
{"dmask=0x1 data_dwords=2 data_bits=16 component=0/4", 1}};
|
||||
test.required_spirv = {"OpImageGather", "PackHalf2x16"};
|
||||
return test;
|
||||
}
|
||||
@@ -19196,8 +19167,6 @@ TestCase ImageD16StoreUnpacksHalfPairs() {
|
||||
test.storage_image_rgba = MakeRgbaImage(4, 4);
|
||||
test.expected_storage_image_rgba = expected_image;
|
||||
test.decoded_counts = {{"d16=1", 1}};
|
||||
test.native_ir_counts = {
|
||||
{"dmask=0xf data_dwords=2 data_bits=16 component=0/4", 1}};
|
||||
test.required_spirv = {"UnpackHalf2x16", "OpImageWrite"};
|
||||
return test;
|
||||
}
|
||||
@@ -19213,11 +19182,10 @@ void CheckIndirectImageKeySwitch() {
|
||||
program.srt_plan_complete = true;
|
||||
program.resource_tracking_complete = true;
|
||||
program.shader_info_complete = true;
|
||||
program.values = std::make_shared<ValueProgram>();
|
||||
program.values->block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.values->block_storage.back().get();
|
||||
program.values->blocks.push_back(block);
|
||||
program.values->block_info.push_back({.id = 0});
|
||||
program.block_storage.push_back(std::make_unique<Block>());
|
||||
auto *block = program.block_storage.back().get();
|
||||
program.blocks.push_back(block);
|
||||
program.block_info.push_back({.id = 0});
|
||||
|
||||
auto &key = block->AppendNewInst(ValueOpcode::LaneId);
|
||||
auto &image =
|
||||
@@ -19242,7 +19210,7 @@ void CheckIndirectImageKeySwitch() {
|
||||
memory.image_sample_flags = ShaderRecompiler::Decoder::ImageSampleFlagLod;
|
||||
memory.image_dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||
memory.image_address_components = 3;
|
||||
program.values->memory_info.push_back(memory);
|
||||
program.memory_info.push_back(memory);
|
||||
const MemoryFlags memory_flags{0u, 0x10f0u};
|
||||
uint64_t memory_flag_bits = 0;
|
||||
std::memcpy(&memory_flag_bits, &memory_flags, sizeof(memory_flags));
|
||||
@@ -19253,11 +19221,11 @@ void CheckIndirectImageKeySwitch() {
|
||||
{Value(&sample), Value(0u)});
|
||||
block->AppendNewInst(ValueOpcode::ReferenceU32, {Value(&sample_x)});
|
||||
|
||||
program.values->descriptor_sources.resize(2);
|
||||
program.values->descriptor_sources[0].dword_count = 8;
|
||||
program.values->descriptor_sources[0].indirect_image =
|
||||
program.descriptor_sources.resize(2);
|
||||
program.descriptor_sources[0].dword_count = 8;
|
||||
program.descriptor_sources[0].indirect_image =
|
||||
DescriptorSource::IndirectImage{0u, 0u, 224u, 12u, 0u};
|
||||
program.values->descriptor_sources[1].dword_count = 4;
|
||||
program.descriptor_sources[1].dword_count = 4;
|
||||
|
||||
ImageResource root{};
|
||||
root.source = 0;
|
||||
@@ -20394,8 +20362,8 @@ void CheckPs5GameExampleImageClearRuntimeShape() {
|
||||
const auto code = MakeCode();
|
||||
auto positive = Compile("exact Prospero kernel", code);
|
||||
|
||||
compute.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(positive.program);
|
||||
compute.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
std::move(positive.program));
|
||||
compute.stage.resources =
|
||||
std::make_shared<const ShaderRecompiler::IR::ResourceSnapshot>(
|
||||
positive.resources);
|
||||
@@ -20488,7 +20456,8 @@ void CheckEmbeddedFetchVertexOffset() {
|
||||
Require(name, "compile",
|
||||
ShaderRecompiler::TryRecompile(code, options, result, &error),
|
||||
error);
|
||||
Require(name, "fetch rewrite", vertex.resource_fetch_components[0] == 4,
|
||||
Require(name, "fetch rewrite",
|
||||
result.program.info.vertex_fetch_components[0] == 4,
|
||||
"encoded fetch sequence was not recognized and rewritten");
|
||||
return result;
|
||||
};
|
||||
@@ -20497,8 +20466,11 @@ void CheckEmbeddedFetchVertexOffset() {
|
||||
u32 index_offset) {
|
||||
ShaderVertexInputInfo vertex;
|
||||
vertex.fetch_embedded = true;
|
||||
vertex.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(result.program);
|
||||
auto program = std::make_shared<ShaderRecompiler::IR::Program>();
|
||||
program->user_data_base = result.program.user_data_base;
|
||||
program->info.vertex_offset_sgpr =
|
||||
result.program.info.vertex_offset_sgpr;
|
||||
vertex.stage.program = std::move(program);
|
||||
vertex.stage.resources =
|
||||
std::make_shared<const ShaderRecompiler::IR::ResourceSnapshot>(
|
||||
result.resources);
|
||||
@@ -22366,52 +22338,55 @@ void CheckImageSpecializationId() {
|
||||
HW::ComputeShaderInfo regs{};
|
||||
regs.cs_regs.data_addr = reinterpret_cast<uint64_t>(code.data());
|
||||
|
||||
ShaderRecompiler::IR::Program identity_program;
|
||||
identity_program.binding_layout_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource image;
|
||||
image.kind = ShaderRecompiler::IR::ResourceKind::StorageImage;
|
||||
image.dimension = ShaderRecompiler::Decoder::ImageDimension::Dim2D;
|
||||
identity_program.info.images.push_back(image);
|
||||
auto rgb1_program = identity_program;
|
||||
rgb1_program.info.images[0].shader_swizzle = DstSel(4, 5, 6, 1);
|
||||
auto converted_program = identity_program;
|
||||
converted_program.info.images[0].conversion_format =
|
||||
const auto make_program = [](ShaderRecompiler::IR::ImageResource resource) {
|
||||
ShaderRecompiler::IR::Program program;
|
||||
program.binding_layout_complete = true;
|
||||
program.info.images.push_back(std::move(resource));
|
||||
return program;
|
||||
};
|
||||
auto rgb1_image = image;
|
||||
rgb1_image.shader_swizzle = DstSel(4, 5, 6, 1);
|
||||
auto converted_image = image;
|
||||
converted_image.conversion_format =
|
||||
Prospero::BufferFormat::k11_11_10UInt;
|
||||
auto mip1_program = identity_program;
|
||||
mip1_program.info.images[0].mip_mode =
|
||||
ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
||||
auto mip3_program = mip1_program;
|
||||
mip3_program.info.images[0].mip_count = 3;
|
||||
auto array_program = identity_program;
|
||||
array_program.info.images[0].dimension =
|
||||
auto mip1_image = image;
|
||||
mip1_image.mip_mode = ShaderRecompiler::IR::ImageMipMode::DynamicStorage;
|
||||
auto mip3_image = mip1_image;
|
||||
mip3_image.mip_count = 3;
|
||||
auto array_image = image;
|
||||
array_image.dimension =
|
||||
ShaderRecompiler::Decoder::ImageDimension::Dim2DArray;
|
||||
auto cube_program = array_program;
|
||||
cube_program.info.images[0].cube = true;
|
||||
auto cube_image = array_image;
|
||||
cube_image.cube = true;
|
||||
|
||||
const auto resources =
|
||||
std::make_shared<const ShaderRecompiler::IR::ResourceSnapshot>();
|
||||
ShaderComputeInputInfo identity_info;
|
||||
identity_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(identity_program);
|
||||
identity_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(image));
|
||||
identity_info.stage.resources = resources;
|
||||
auto rgb1_info = identity_info;
|
||||
rgb1_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(rgb1_program);
|
||||
rgb1_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(rgb1_image));
|
||||
auto converted_info = identity_info;
|
||||
converted_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(converted_program);
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(converted_image));
|
||||
auto mip1_info = identity_info;
|
||||
mip1_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(mip1_program);
|
||||
mip1_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(mip1_image));
|
||||
auto mip3_info = identity_info;
|
||||
mip3_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(mip3_program);
|
||||
mip3_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(mip3_image));
|
||||
auto array_info = identity_info;
|
||||
array_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(array_program);
|
||||
array_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(array_image));
|
||||
auto cube_info = identity_info;
|
||||
cube_info.stage.program =
|
||||
std::make_shared<const ShaderRecompiler::IR::Program>(cube_program);
|
||||
cube_info.stage.program = std::make_shared<const ShaderRecompiler::IR::Program>(
|
||||
make_program(cube_image));
|
||||
|
||||
const auto identity_id = ShaderGetIdCS(regs, identity_info, true);
|
||||
const auto rgb1_id = ShaderGetIdCS(regs, rgb1_info, true);
|
||||
@@ -22452,8 +22427,6 @@ void CheckImageSpecializationId() {
|
||||
"forcing point filtering enabled mipmapping on a base-mip sampler");
|
||||
|
||||
ShaderRecompiler::IR::Program mixed_sampler_program;
|
||||
mixed_sampler_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
mixed_sampler_program.resource_tracking_complete = true;
|
||||
ShaderRecompiler::IR::ImageResource sampled_image;
|
||||
sampled_image.kind = ShaderRecompiler::IR::ResourceKind::Image;
|
||||
@@ -22500,8 +22473,6 @@ void CheckImageSpecializationId() {
|
||||
"native variants");
|
||||
|
||||
ShaderRecompiler::IR::Program packed_atomic_program;
|
||||
packed_atomic_program.values =
|
||||
std::make_shared<ShaderRecompiler::IR::ValueProgram>();
|
||||
packed_atomic_program.resource_tracking_complete = true;
|
||||
auto packed_atomic_image = sampled_image;
|
||||
packed_atomic_image.kind =
|
||||
@@ -23245,7 +23216,7 @@ void CheckEmbeddedFetchLaneSpill() {
|
||||
Require("EmbeddedFetchLaneSpill", "compile",
|
||||
ShaderRecompiler::TryRecompile(code, options, result, &error), error);
|
||||
Require("EmbeddedFetchLaneSpill", "fetch rewrite",
|
||||
vertex.resource_fetch_components[0] == 4,
|
||||
result.program.info.vertex_fetch_components[0] == 4,
|
||||
"lane-spilled fetch descriptor was not recognized and rewritten");
|
||||
std::printf("[host] %-32s ok\n", "EmbeddedFetchLaneSpill");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||
#include "graphics/shader/recompiler/ir/ShaderIR.h"
|
||||
#include "graphics/shader/recompiler/ir/passes/ResourceMaterialization.h"
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
@@ -23,12 +23,11 @@ bool RejectSpecializationRead(void *userdata, uint64_t, uint32_t *) {
|
||||
Libs::Graphics::ShaderRecompiler::IR::Block &
|
||||
AddValueBlock(Libs::Graphics::ShaderRecompiler::IR::Program &program) {
|
||||
using namespace Libs::Graphics::ShaderRecompiler::IR;
|
||||
program.values = std::make_shared<ValueProgram>();
|
||||
auto block = std::make_unique<Block>();
|
||||
auto *result = block.get();
|
||||
program.values->blocks.push_back(result);
|
||||
program.values->block_info.push_back({.id = 0});
|
||||
program.values->block_storage.push_back(std::move(block));
|
||||
program.blocks.push_back(result);
|
||||
program.block_info.push_back({.id = 0});
|
||||
program.block_storage.push_back(std::move(block));
|
||||
return *result;
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ SrtProgram(uint64_t address) {
|
||||
MemoryInfo memory;
|
||||
memory.kind = ResourceKind::ScalarAddress;
|
||||
memory.planning_only = true;
|
||||
program.values->memory_info.push_back(memory);
|
||||
program.memory_info.push_back(memory);
|
||||
const auto low = Value(static_cast<uint32_t>(address));
|
||||
const auto high = Value(static_cast<uint32_t>(address >> 32u));
|
||||
auto &handle =
|
||||
@@ -53,7 +52,7 @@ SrtProgram(uint64_t address) {
|
||||
ValueOpcode::LoadAddressU32,
|
||||
{Value(&handle), Value(0u), Value(0u), Value(true)});
|
||||
raw.SetFlags(MemoryFlags{.index = 0, .pc = 0x40});
|
||||
program.values->srt_reads.push_back({Value(&raw), 0, 0x40});
|
||||
program.srt_reads.push_back({Value(&raw), 0, 0x40});
|
||||
|
||||
auto &srt = value_block.AppendNewInst(ValueOpcode::GetSrtResource);
|
||||
auto &flat = value_block.AppendNewInst(ValueOpcode::ReadConst,
|
||||
@@ -62,7 +61,7 @@ SrtProgram(uint64_t address) {
|
||||
source.dwords[0] = Value(&flat);
|
||||
source.dwords[1] = Value(0u);
|
||||
source.dword_count = 2;
|
||||
program.values->descriptor_sources.push_back(source);
|
||||
program.descriptor_sources.push_back(source);
|
||||
return std::make_shared<const Program>(std::move(program));
|
||||
}
|
||||
|
||||
@@ -141,5 +140,5 @@ int main() {
|
||||
#include "graphics/shader/recompiler/ir/Block.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Type.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Value.cpp"
|
||||
#include "graphics/shader/recompiler/ir/ValueProgram.cpp"
|
||||
#include "graphics/shader/recompiler/ir/Program.cpp"
|
||||
#include "graphics/shader/recompiler/ir/opcodes/ValueOpcodes.cpp"
|
||||
|
||||
+467
-388
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user