mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
Resolve draw-uniform image descriptors through scalar buffer chains
This commit is contained in:
@@ -535,16 +535,6 @@ private:
|
|||||||
DescriptorSource descriptor;
|
DescriptorSource descriptor;
|
||||||
MakeSource(*handle, width, sampler, sample_adjust, descriptor, pc);
|
MakeSource(*handle, width, sampler, sample_adjust, descriptor, pc);
|
||||||
uint32_t bad_dword = 0;
|
uint32_t bad_dword = 0;
|
||||||
if (expected == ValueOpcode::GetImageResource) {
|
|
||||||
for (; bad_dword < descriptor.dword_count; bad_dword++) {
|
|
||||||
const auto* value = descriptor.dwords[bad_dword].Resolve().TryInstruction();
|
|
||||||
if (value != nullptr && value->GetOpcode() == ValueOpcode::ReadConstBuffer) {
|
|
||||||
Fail(pc, fmt::format("{} dword {} is not a valid runtime value",
|
|
||||||
ValueOpcodeName(expected), bad_dword));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bad_dword = 0;
|
|
||||||
}
|
|
||||||
if (!ValidateSource(descriptor, bad_dword)) {
|
if (!ValidateSource(descriptor, bad_dword)) {
|
||||||
if (expected == ValueOpcode::GetBufferResource &&
|
if (expected == ValueOpcode::GetBufferResource &&
|
||||||
std::all_of(descriptor.dwords.begin(), descriptor.dwords.begin() + width,
|
std::all_of(descriptor.dwords.begin(), descriptor.dwords.begin() + width,
|
||||||
|
|||||||
@@ -213,8 +213,11 @@ MakeIndirectImageFixture(bool malformed, uint32_t material_immediate = 0,
|
|||||||
fixture->AddMemory(shared_buffer, 0x10d8));
|
fixture->AddMemory(shared_buffer, 0x10d8));
|
||||||
fixture->Emit(ValueOpcode::ReferenceU32, {load});
|
fixture->Emit(ValueOpcode::ReferenceU32, {load});
|
||||||
}
|
}
|
||||||
|
const auto invocation = fixture->Emit(
|
||||||
|
ValueOpcode::GetBuiltin,
|
||||||
|
{Value(static_cast<uint32_t>(StageInputKind::GlobalInvocationId)), Value(0u)});
|
||||||
const auto selector = fixture->Emit(ValueOpcode::ReadFirstLane,
|
const auto selector = fixture->Emit(ValueOpcode::ReadFirstLane,
|
||||||
{fixture->UserData(8), Value(true)});
|
{invocation, Value(true)});
|
||||||
const auto record =
|
const auto record =
|
||||||
fixture->Emit(ValueOpcode::IMul32, {selector, Value(224u)});
|
fixture->Emit(ValueOpcode::IMul32, {selector, Value(224u)});
|
||||||
const auto member = fixture->Emit(ValueOpcode::IAdd32, {record, Value(4u)});
|
const auto member = fixture->Emit(ValueOpcode::IAdd32, {record, Value(4u)});
|
||||||
@@ -457,6 +460,83 @@ void TestInvariantIndirectImageMaterialization() {
|
|||||||
"wrapped scalar immediate entered the invariant image proof");
|
"wrapped scalar immediate entered the invariant image proof");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestUniformScalarBufferImage() {
|
||||||
|
Fixture fixture(ShaderType::Pixel);
|
||||||
|
std::array<Value, 4> material_words;
|
||||||
|
std::array<Value, 4> heap_words;
|
||||||
|
for (uint32_t dword = 0; dword < 4; dword++) {
|
||||||
|
material_words[dword] = fixture.UserData(dword);
|
||||||
|
heap_words[dword] = fixture.UserData(dword + 4u);
|
||||||
|
}
|
||||||
|
const auto material = fixture.Buffer(material_words);
|
||||||
|
const auto heap = fixture.Buffer(heap_words);
|
||||||
|
const auto selector = fixture.Emit(ValueOpcode::ShiftLeftLogical32,
|
||||||
|
{fixture.UserData(8), Value(2u)});
|
||||||
|
MemoryInfo scalar;
|
||||||
|
scalar.kind = ResourceKind::ScalarBuffer;
|
||||||
|
scalar.offset = 0x40u;
|
||||||
|
const auto key = fixture.Emit(ValueOpcode::ReadConstBuffer,
|
||||||
|
{material, selector}, fixture.AddMemory(scalar, 0x100));
|
||||||
|
const auto record = fixture.Emit(ValueOpcode::IMul32, {key, Value(48u)});
|
||||||
|
std::array<Value, 8> image_words;
|
||||||
|
for (uint32_t dword = 0; dword < image_words.size(); dword++) {
|
||||||
|
scalar.offset = 0x10u + dword * sizeof(uint32_t);
|
||||||
|
image_words[dword] = fixture.Emit(ValueOpcode::ReadConstBuffer,
|
||||||
|
{heap, record}, fixture.AddMemory(scalar, 0x200));
|
||||||
|
}
|
||||||
|
const auto image = fixture.Image(image_words);
|
||||||
|
const auto sampler = fixture.Sampler({Value(0u), Value(0u), Value(0u), Value(0u)});
|
||||||
|
MemoryInfo sample;
|
||||||
|
sample.kind = ResourceKind::Image;
|
||||||
|
sample.image_dimension = Decoder::ImageDimension::Dim2D;
|
||||||
|
fixture.Emit(ValueOpcode::ImageSampleRaw,
|
||||||
|
{image, sampler, fixture.ImageAddress()}, fixture.AddMemory(sample, 0x228));
|
||||||
|
fixture.PlanAndTrack();
|
||||||
|
const auto plan = ExtractResourcePlan(fixture.program);
|
||||||
|
|
||||||
|
std::array<uint32_t, 9> user_data{0x1000u, 0u, 0x100u, 0u,
|
||||||
|
0x2000u, 0u, 0x100u, 0u, 0u};
|
||||||
|
LinearTestMemory memory;
|
||||||
|
memory.words[0x44u / 4u] = 1u;
|
||||||
|
std::array<uint32_t, 8> descriptor{};
|
||||||
|
descriptor[0] = 0x20u;
|
||||||
|
descriptor[1] = static_cast<uint32_t>(
|
||||||
|
Libs::Graphics::Prospero::BufferFormat::k32_32_32_32Float)
|
||||||
|
<< 20u;
|
||||||
|
descriptor[2] = 3u | (3u << 14u);
|
||||||
|
descriptor[3] = Libs::Graphics::DstSel(4, 5, 6, 7) |
|
||||||
|
(static_cast<uint32_t>(Libs::Graphics::Prospero::ImageType::kColor2D)
|
||||||
|
<< 28u);
|
||||||
|
for (uint32_t index = 0; index < 2; index++) {
|
||||||
|
std::copy(descriptor.begin(), descriptor.end(),
|
||||||
|
memory.words.begin() + (0x1010u + index * 48u) / 4u);
|
||||||
|
memory.words[(0x1010u + index * 48u) / 4u] += index;
|
||||||
|
}
|
||||||
|
SrtRuntime runtime{.user_data = user_data,
|
||||||
|
.read_memory = ReadLinearTestMemory,
|
||||||
|
.userdata = &memory,
|
||||||
|
.read_specialization_memory = ReadLinearTestMemory};
|
||||||
|
ResourceSnapshot snapshot;
|
||||||
|
ResourceSpecialization specialization;
|
||||||
|
const auto materializes = [&](uint32_t address) {
|
||||||
|
return MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
|
snapshot.images.size() == 1 && snapshot.images[0].dwords[0] == address;
|
||||||
|
};
|
||||||
|
Check(materializes(0x20u), "nested draw-uniform image descriptor did not materialize");
|
||||||
|
user_data[8] = 1u;
|
||||||
|
Check(materializes(0x21u), "changed draw selector reused the previous image descriptor");
|
||||||
|
memory.words[0x44u / 4u] = 0u;
|
||||||
|
memory.words[0x1010u / 4u] = 0x30u;
|
||||||
|
Check(materializes(0x30u), "changed scalar table memory reused the previous image descriptor");
|
||||||
|
const auto prior_snapshot = snapshot;
|
||||||
|
const auto prior_specialization = specialization;
|
||||||
|
memory.fail_address = 0x1044u;
|
||||||
|
Check(!MaterializeResources(plan, runtime, snapshot, specialization) &&
|
||||||
|
SameResourceSnapshot(snapshot, prior_snapshot) &&
|
||||||
|
specialization == prior_specialization,
|
||||||
|
"unavailable nested image table partially changed the resource snapshot");
|
||||||
|
}
|
||||||
|
|
||||||
void TestComputeBufferFill() {
|
void TestComputeBufferFill() {
|
||||||
struct Options {
|
struct Options {
|
||||||
bool scalar = false;
|
bool scalar = false;
|
||||||
@@ -2013,6 +2093,7 @@ int main() {
|
|||||||
Run("FMASK load specialization", TestFmaskLoadSpecialization);
|
Run("FMASK load specialization", TestFmaskLoadSpecialization);
|
||||||
Run("dynamic storage mips", TestDynamicStorageMipTracking);
|
Run("dynamic storage mips", TestDynamicStorageMipTracking);
|
||||||
Run("invariant indirect images", TestInvariantIndirectImageMaterialization);
|
Run("invariant indirect images", TestInvariantIndirectImageMaterialization);
|
||||||
|
Run("draw-uniform scalar image", TestUniformScalarBufferImage);
|
||||||
Run("SRT runtime", TestSrtFlatteningAndRuntimeMemoization);
|
Run("SRT runtime", TestSrtFlatteningAndRuntimeMemoization);
|
||||||
Run("dynamic SRT", TestDynamicSrtReadRemainsExplicit);
|
Run("dynamic SRT", TestDynamicSrtReadRemainsExplicit);
|
||||||
Run("phi validation", TestPhiValidation);
|
Run("phi validation", TestPhiValidation);
|
||||||
|
|||||||
Reference in New Issue
Block a user