mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-25 20:36:54 +01:00
pipeline: create pipelines from GraphicsPipelineKey and shader modules
This commit is contained in:
@@ -92,6 +92,7 @@
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include <ranges>
|
||||
#include <semaphore>
|
||||
#include <set>
|
||||
#include <span>
|
||||
@@ -447,7 +448,7 @@ struct RenderExecutorTestAccess {
|
||||
std::vector<vk::DescriptorSetLayoutBinding> layout_bindings;
|
||||
bool compute = false;
|
||||
for (const auto *prepared : stages) {
|
||||
const auto &program = *prepared->runtime->program;
|
||||
const auto &program = prepared->runtime->module->info;
|
||||
compute |= program.stage == ShaderType::Compute;
|
||||
const auto shader_stage = program.stage == ShaderType::Vertex
|
||||
? vk::ShaderStageFlagBits::eVertex
|
||||
@@ -498,7 +499,7 @@ struct RenderExecutorTestAccess {
|
||||
PreparedBindings &bindings) {
|
||||
std::array<PreparedBindings *, 1> stages{&bindings};
|
||||
auto pipeline = CreateDescriptorPipeline(executor, stages);
|
||||
const auto bind_point = bindings.runtime->program->stage == ShaderType::Compute
|
||||
const auto bind_point = bindings.runtime->module->info.stage == ShaderType::Compute
|
||||
? vk::PipelineBindPoint::eCompute
|
||||
: vk::PipelineBindPoint::eGraphics;
|
||||
executor.CommitBindings(buffer, bind_point, pipeline, stages);
|
||||
@@ -583,6 +584,33 @@ struct RenderExecutorTestAccess {
|
||||
}
|
||||
};
|
||||
|
||||
struct PipelineCacheTestAccess {
|
||||
// Replaces each graphics pipeline whose stage ids name compiled modules with one created
|
||||
// from only its key and those modules. The GPU must be idle. Returns how many it replaced.
|
||||
static uint32_t RecreateGraphicsPipelines(PipelineCache &cache) {
|
||||
std::unordered_map<uint64_t, const ShaderModule *> modules{{0, nullptr}}; // Id 0: absent.
|
||||
for (const auto &program : cache.m_program_cache | std::views::values)
|
||||
for (const auto &module : program.modules) modules.emplace(module.id, &module);
|
||||
auto &device = cache.m_graphics.device;
|
||||
uint32_t count = 0;
|
||||
for (auto &[key, pipeline] : cache.m_graphics_pipelines) {
|
||||
// Test-owned modules are not in the cache.
|
||||
if (!std::ranges::all_of(key.stage_ids, [&](uint64_t id) { return modules.contains(id); }))
|
||||
continue;
|
||||
std::array<const ShaderModule *, 4> stages{};
|
||||
for (size_t i = 0; i < stages.size(); i++) stages[i] = modules.at(key.stage_ids[i]);
|
||||
PipelineCache::Pipeline recreated;
|
||||
CreatePipelineInternal(cache.m_graphics, recreated, key, stages, nullptr);
|
||||
device.destroyPipeline(pipeline.pipeline, nullptr);
|
||||
device.destroyPipelineLayout(pipeline.pipeline_layout, nullptr);
|
||||
device.destroyDescriptorSetLayout(pipeline.descriptor_set_layout, nullptr);
|
||||
pipeline = recreated;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
using u32 = uint32_t;
|
||||
@@ -1509,18 +1537,12 @@ void CheckRectListShaders() {
|
||||
program.info.inputs.push_back(
|
||||
{ShaderRecompiler::IR::StageInputKind::Parameter, 1, 4, "in_param_1"});
|
||||
|
||||
ShaderVertexInputInfo vertex{};
|
||||
ShaderRecompiler::IR::CompiledShaderInfo vertex_program{.param_export_mask = 1u};
|
||||
ShaderRecompiler::IR::ResourceSnapshot empty_snapshot;
|
||||
vertex.stage.program = &vertex_program;
|
||||
vertex.stage.resources = &empty_snapshot;
|
||||
constexpr uint32_t param_export_mask = 1u;
|
||||
ShaderPixelInputInfo pixel{};
|
||||
pixel.parameter_mode = ShaderPixelParameterMode::Rectangle;
|
||||
pixel.input_num = 2;
|
||||
pixel.interpolator_settings[0] = 0x400u;
|
||||
pixel.interpolator_settings[1] = 0;
|
||||
pixel.stage.program = &program;
|
||||
pixel.stage.resources = &empty_snapshot;
|
||||
std::vector<uint32_t> perspective_specialization;
|
||||
BuildStageStaticKey(pixel, perspective_specialization);
|
||||
pixel.ps_no_perspective = true;
|
||||
@@ -1539,7 +1561,8 @@ void CheckRectListShaders() {
|
||||
"duplicate pixel mappings must receive distinct effective output "
|
||||
"locations");
|
||||
|
||||
const auto shaders = BuildRectListShaders(vertex, &pixel);
|
||||
const auto shaders =
|
||||
BuildRectListShaders(RectListParameters(pixel, program), param_export_mask);
|
||||
Require(name, "SPIR-V version",
|
||||
shaders.control.size() > 1 && shaders.control[1] == 0x00010500u &&
|
||||
shaders.evaluation.size() > 1 &&
|
||||
@@ -1588,7 +1611,8 @@ void CheckRectListShaders() {
|
||||
for (const auto flat : {0u, 0x400u}) {
|
||||
pixel.interpolator_settings[0] = flat;
|
||||
pixel.interpolator_settings[1] = flat;
|
||||
const auto shared = BuildRectListShaders(vertex, &pixel);
|
||||
const auto shared =
|
||||
BuildRectListShaders(RectListParameters(pixel, program), param_export_mask);
|
||||
ValidateSpirv(name, shared.control);
|
||||
ValidateSpirv(name, shared.evaluation);
|
||||
Require(name, "same-mode alias disassembly",
|
||||
@@ -1604,7 +1628,7 @@ void CheckRectListShaders() {
|
||||
"the shared location in each rectangle-list stage");
|
||||
}
|
||||
|
||||
const auto position_only = BuildRectListShaders(vertex, nullptr);
|
||||
const auto position_only = BuildRectListShaders({}, param_export_mask);
|
||||
ValidateSpirv(name, position_only.control);
|
||||
ValidateSpirv(name, position_only.evaluation);
|
||||
}
|
||||
@@ -2210,22 +2234,24 @@ public:
|
||||
HW::Shader shaders{};
|
||||
scheduler.Begin(registers, user_config, shaders);
|
||||
|
||||
ShaderRecompiler::IR::CompiledShaderInfo vertex_program{};
|
||||
ShaderModule vertex_module;
|
||||
auto &vertex_program = vertex_module.info;
|
||||
vertex_program.stage = ShaderType::Vertex;
|
||||
vertex_program.bindings.push_data_start_dword = 2;
|
||||
vertex_program.info.user_data_registers = {0, 1};
|
||||
vertex_program.bindings.memory_offset_dword = 2;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo pixel_program{};
|
||||
ShaderModule pixel_module;
|
||||
auto &pixel_program = pixel_module.info;
|
||||
pixel_program.stage = ShaderType::Pixel;
|
||||
pixel_program.bindings.push_data_start_dword = 0;
|
||||
pixel_program.info.user_data_registers = {0, 1};
|
||||
pixel_program.bindings.memory_offset_dword = 2;
|
||||
ShaderRecompiler::IR::ResourceSnapshot vertex_snapshot;
|
||||
vertex_snapshot.user_data = {0x11111111u, 0x22222222u};
|
||||
ShaderStageRuntime vertex_runtime{&vertex_program, &vertex_snapshot};
|
||||
ShaderStageRuntime vertex_runtime{&vertex_module, &vertex_snapshot};
|
||||
ShaderRecompiler::IR::ResourceSnapshot pixel_snapshot;
|
||||
pixel_snapshot.user_data = {0x33333333u, 0x44444444u};
|
||||
ShaderStageRuntime pixel_runtime{&pixel_program, &pixel_snapshot};
|
||||
ShaderStageRuntime pixel_runtime{&pixel_module, &pixel_snapshot};
|
||||
PreparedBindings vertex;
|
||||
PreparedBindings pixel;
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
@@ -5520,8 +5546,9 @@ public:
|
||||
"test HTile entries were not registered in their initial state");
|
||||
|
||||
const auto MakeInput = [](uint64_t address, bool read, bool written,
|
||||
ShaderRecompiler::IR::CompiledShaderInfo &program,
|
||||
ShaderModule &module,
|
||||
ShaderRecompiler::IR::ResourceSnapshot &snapshot) {
|
||||
auto &program = module.info;
|
||||
program.stage = ShaderType::Compute;
|
||||
ShaderRecompiler::IR::BufferResource resource{};
|
||||
resource.read = read;
|
||||
@@ -5541,14 +5568,14 @@ public:
|
||||
value.dword_count = 4;
|
||||
std::copy_n(descriptor.fields, value.dword_count, value.dwords.begin());
|
||||
ShaderComputeInputInfo input{};
|
||||
input.stage.program = &program;
|
||||
input.stage.module = &module;
|
||||
snapshot.buffers.push_back(value);
|
||||
input.stage.resources = &snapshot;
|
||||
return input;
|
||||
};
|
||||
auto &executor = context.GetRenderExecutor();
|
||||
auto &command = scheduler.Current();
|
||||
ShaderRecompiler::IR::CompiledShaderInfo read_only_program{};
|
||||
ShaderModule read_only_program;
|
||||
ShaderRecompiler::IR::ResourceSnapshot read_only_snapshot;
|
||||
const auto read_only_input =
|
||||
MakeInput(read_only_meta, true, false, read_only_program,
|
||||
@@ -5561,7 +5588,7 @@ public:
|
||||
!texture_cache.IsMetaCleared(read_only_meta, 0),
|
||||
"a metadata read-only dispatch changed logical clear state");
|
||||
|
||||
ShaderRecompiler::IR::CompiledShaderInfo read_write_program{};
|
||||
ShaderModule read_write_program;
|
||||
ShaderRecompiler::IR::ResourceSnapshot read_write_snapshot;
|
||||
const auto read_write_input =
|
||||
MakeInput(read_write_meta, true, true, read_write_program,
|
||||
@@ -5574,7 +5601,7 @@ public:
|
||||
!texture_cache.IsMetaCleared(read_write_meta, 0),
|
||||
"a metadata read/modify/write dispatch was replaced by a clear");
|
||||
|
||||
ShaderRecompiler::IR::CompiledShaderInfo write_only_program{};
|
||||
ShaderModule write_only_program;
|
||||
ShaderRecompiler::IR::ResourceSnapshot write_only_snapshot;
|
||||
const auto write_only_input =
|
||||
MakeInput(write_only_meta, false, true, write_only_program,
|
||||
@@ -11099,9 +11126,9 @@ public:
|
||||
ShaderComputeInputInfo input{};
|
||||
const auto program = context.GetPipelineCache().GetComputeProgram(
|
||||
shaders.GetCs(), input);
|
||||
if (original_id == 0) original_id = program.id;
|
||||
if (original_id == 0) original_id = program->id;
|
||||
Require(name, "exact function identity",
|
||||
(program.id == original_id) == (test.value == 41),
|
||||
(program->id == original_id) == (test.value == 41),
|
||||
"helper bytes were stale or identical relocated/restored code recompiled");
|
||||
Require(name, "current code dependency",
|
||||
std::ranges::find(input.stage.resources->specialization_reads,
|
||||
@@ -11191,9 +11218,9 @@ public:
|
||||
ShaderComputeInputInfo input{};
|
||||
const auto program = context.GetPipelineCache().GetComputeProgram(
|
||||
shaders.GetCs(), input);
|
||||
if (phase == 1) original_vector_id = program.id;
|
||||
if (phase == 1) original_vector_id = program->id;
|
||||
if (phase >= 2)
|
||||
Require(name, "ordered helper identity", (program.id == original_vector_id) == (phase == 3),
|
||||
Require(name, "ordered helper identity", (program->id == original_vector_id) == (phase == 3),
|
||||
"swapped helper targets reused stale code or restored targets recompiled");
|
||||
const auto& reads = input.stage.resources->specialization_reads;
|
||||
for (u32 i = 0; i < (call_count == 1 ? 1u : 2u); ++i)
|
||||
@@ -11689,7 +11716,7 @@ public:
|
||||
Prospero::BufferFormat::k32UInt, Prospero::ImageType::kColor2D,
|
||||
{8, 1, 1}, 1, 4, 1);
|
||||
const auto image = textures.FindImage(image_desc);
|
||||
ShaderProgram previous_program;
|
||||
uint64_t previous_id = 0;
|
||||
for (const auto count : {3u, 7u}) {
|
||||
cache.FillBuffer(count_output, 16u * sizeof(u32), sentinel, false);
|
||||
shaders.SetCsShader({.data_addr = reinterpret_cast<uint64_t>(writer.data()),
|
||||
@@ -11734,11 +11761,11 @@ public:
|
||||
ShaderComputeInputInfo input{};
|
||||
const auto program = context.GetPipelineCache().GetComputeProgram(
|
||||
shaders.GetCs(), input);
|
||||
if (previous_program.id != 0) {
|
||||
Require(name, "count permutation reuse", program.id == previous_program.id,
|
||||
if (previous_id != 0) {
|
||||
Require(name, "count permutation reuse", program->id == previous_id,
|
||||
"a changing GPU count compiled a new shader permutation");
|
||||
}
|
||||
previous_program = program;
|
||||
previous_id = program->id;
|
||||
Require(name, "clean count repeat",
|
||||
CpOpDispatchIndirect(processor, 0xc0021600u, packet.data(), 0, 0) == 3 &&
|
||||
scheduler.CurrentTick() == clean_tick,
|
||||
@@ -11818,29 +11845,29 @@ public:
|
||||
shaders.GetCs(), input);
|
||||
Require(name, "workgroup table refresh and coalescing",
|
||||
input.workgroup_counts[2] == test.groups &&
|
||||
input.stage.program->info.images.size() == 1 &&
|
||||
input.stage.program->info.images[0].indirect_resources.empty() &&
|
||||
input.stage.module->info.info.images.size() == 1 &&
|
||||
input.stage.module->info.info.images[0].indirect_resources.empty() &&
|
||||
input.stage.resources->images.size() == 1 &&
|
||||
std::equal(std::begin(sharp.fields), std::end(sharp.fields),
|
||||
input.stage.resources->images[0].dwords.begin()) &&
|
||||
!input.stage.program->info.buffers.empty(),
|
||||
!input.stage.module->info.info.buffers.empty(),
|
||||
"workgroup bounds, refreshed sharp, or live descriptor dimension reads were lost");
|
||||
Require(name, "workgroup table program reuse",
|
||||
table_program_id == 0 || program.id == table_program_id,
|
||||
table_program_id == 0 || program->id == table_program_id,
|
||||
"changing the workgroup count or identical sharp values recompiled the shader");
|
||||
table_program_id = program.id;
|
||||
table_program_id = program->id;
|
||||
const auto *snapshot = input.stage.resources;
|
||||
const auto *image_storage = snapshot->images.data();
|
||||
const auto flattened_capacity = snapshot->flattened_srt.capacity();
|
||||
const auto repeated = context.GetPipelineCache().GetComputeProgram(
|
||||
shaders.GetCs(), input);
|
||||
Require(name, "workgroup table cache-hit storage reuse",
|
||||
repeated.id == program.id && input.stage.resources == snapshot &&
|
||||
repeated->id == program->id && input.stage.resources == snapshot &&
|
||||
snapshot->images.data() == image_storage &&
|
||||
snapshot->flattened_srt.capacity() == flattened_capacity,
|
||||
"a repeated descriptor table hit replaced its snapshot or storage");
|
||||
auto binding = RenderExecutorTestAccess::ResolveTexture(
|
||||
context.GetRenderExecutor(), input.stage.program->info.images[0],
|
||||
context.GetRenderExecutor(), input.stage.module->info.info.images[0],
|
||||
input.stage.resources->images[0]);
|
||||
const auto target = textures.FindImage(binding.desc);
|
||||
TextureCacheTestAccess::ClearImage(textures, scheduler.Current(), target,
|
||||
@@ -12073,11 +12100,11 @@ public:
|
||||
input.workgroup_counts[1] = input.workgroup_counts[2] = 1u;
|
||||
(void)context.GetPipelineCache().GetComputeProgram(
|
||||
shaders.GetCs(), input);
|
||||
const auto &info = input.stage.program->info;
|
||||
const auto &info = input.stage.module->info.info;
|
||||
const auto root = std::ranges::find_if(info.buffers, [](const auto &buffer) {
|
||||
return buffer.indirect_resources.size() == material_rows;
|
||||
});
|
||||
const auto &bindings = input.stage.program->bindings;
|
||||
const auto &bindings = input.stage.module->info.bindings;
|
||||
const auto native_count = bindings.descriptor_counts[
|
||||
static_cast<size_t>(ShaderRecompiler::IR::DescriptorBindingKind::Buffers)];
|
||||
Require(name, "native material descriptor array",
|
||||
@@ -14331,14 +14358,15 @@ public:
|
||||
};
|
||||
const auto make_buffer_program =
|
||||
[](ShaderType stage, ShaderRecompiler::IR::BufferResource resource) {
|
||||
ShaderRecompiler::IR::CompiledShaderInfo program{};
|
||||
ShaderModule module;
|
||||
auto &program = module.info;
|
||||
program.stage = stage;
|
||||
resource.descriptor_index = 0;
|
||||
program.info.buffers.push_back(resource);
|
||||
program.bindings.descriptor_counts[0] = 1;
|
||||
program.bindings.descriptor_mask = 1;
|
||||
program.bindings.push_data_start_dword = 0;
|
||||
return program;
|
||||
return module;
|
||||
};
|
||||
|
||||
{
|
||||
@@ -14441,7 +14469,7 @@ public:
|
||||
bindings.buffers[0].buffer == owner.Handle() &&
|
||||
bindings.buffers[0].offset + 2 == owner.Offset(buffer_address) &&
|
||||
bindings.buffers[0].range == 14 &&
|
||||
bindings.shader_data[buffer_program.bindings.memory_offset_dword] == 2,
|
||||
bindings.shader_data[buffer_program.info.bindings.memory_offset_dword] == 2,
|
||||
"native binding lost the byte adjustment or rounded the final halfword range");
|
||||
}
|
||||
|
||||
@@ -14449,7 +14477,8 @@ public:
|
||||
constexpr uint64_t address = base + allocation_size - 0x4000 + 12;
|
||||
constexpr uint64_t mapped_tail = base + allocation_size - address;
|
||||
auto writer = make_buffer_program(ShaderType::Vertex, {.written = true});
|
||||
ShaderRecompiler::IR::CompiledShaderInfo reader{};
|
||||
ShaderModule reader_module;
|
||||
auto &reader = reader_module.info;
|
||||
reader.stage = ShaderType::Pixel;
|
||||
ShaderRecompiler::IR::ResourceSnapshot writer_snapshot, reader_snapshot;
|
||||
ShaderBufferResource descriptor{};
|
||||
@@ -14459,7 +14488,7 @@ public:
|
||||
std::copy_n(descriptor.fields, 4, value.dwords.begin());
|
||||
value.dword_count = 4;
|
||||
ShaderStageRuntime writer_runtime{&writer, &writer_snapshot};
|
||||
ShaderStageRuntime reader_runtime{&reader, &reader_snapshot};
|
||||
ShaderStageRuntime reader_runtime{&reader_module, &reader_snapshot};
|
||||
PreparedBindings writer_bindings, reader_bindings;
|
||||
const auto check_range = [&](uint64_t expected, const char *description) {
|
||||
executor.PrepareBindings(writer_runtime, writer_bindings);
|
||||
@@ -14490,8 +14519,8 @@ public:
|
||||
value.dwords[2] = 0x300;
|
||||
check_range(0x300, "finite write preserves its declared range");
|
||||
value.dwords[2] = UINT32_MAX;
|
||||
writer.info.buffers[0].written = false;
|
||||
writer.info.buffers[0].read = true;
|
||||
writer.info.info.buffers[0].written = false;
|
||||
writer.info.info.buffers[0].read = true;
|
||||
check_range(mapped_tail, "read-only sentinel preserves mapped tail");
|
||||
auto &graphics = context.GetGraphics();
|
||||
auto &storage_limit = graphics.physical_device_properties.limits.maxStorageBufferRange;
|
||||
@@ -14538,7 +14567,8 @@ public:
|
||||
texture_cache.MarkGpuWritten(depth_id);
|
||||
expected = 0xffff;
|
||||
}
|
||||
ShaderRecompiler::IR::CompiledShaderInfo program{};
|
||||
ShaderModule module;
|
||||
auto &program = module.info;
|
||||
program.stage = ShaderType::Compute;
|
||||
ShaderRecompiler::IR::ResourceSnapshot snapshot;
|
||||
// PPSA24156 binds one-texel R8/R16 allocations as 3D, then 2D.
|
||||
@@ -14560,7 +14590,7 @@ public:
|
||||
DstSel(4, 4, 4, 1) | (static_cast<u32>(type) << 28u),
|
||||
0, 0x00700000u, 0, 0};
|
||||
}
|
||||
ShaderStageRuntime runtime{&program, &snapshot};
|
||||
ShaderStageRuntime runtime{&module, &snapshot};
|
||||
PreparedBindings bindings;
|
||||
executor.PrepareBindings(runtime, bindings);
|
||||
Require(name, "overlapping dimension discovery",
|
||||
@@ -14683,11 +14713,12 @@ public:
|
||||
null_program.info.images.back().mip_mode = ShaderRecompiler::IR::ImageMipMode::Dynamic;
|
||||
null_program.info.images.back().mip_count = 3;
|
||||
set_image_bindings(null_program);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo null_info{};
|
||||
ShaderModule null_module;
|
||||
auto &null_info = null_module.info;
|
||||
null_info.stage = null_program.stage;
|
||||
null_info.info = std::move(null_program.info);
|
||||
null_info.bindings = std::move(null_program.bindings);
|
||||
ShaderStageRuntime null_runtime{&null_info, &null_snapshot};
|
||||
ShaderStageRuntime null_runtime{&null_module, &null_snapshot};
|
||||
PreparedBindings null_bindings;
|
||||
executor.PrepareBindings(null_runtime, null_bindings);
|
||||
executor.RebindImages(null_bindings);
|
||||
@@ -14923,7 +14954,8 @@ public:
|
||||
tail4 == std::vector<u32>{tail_backing_value},
|
||||
"expanding a shared mip tail lost GPU writes or the added mip's backing bytes");
|
||||
PreparedBindings mipped_prepared{};
|
||||
ShaderRecompiler::IR::CompiledShaderInfo mipped_program{};
|
||||
ShaderModule mipped_module;
|
||||
auto &mipped_program = mipped_module.info;
|
||||
mipped_program.info.images.push_back(storage_resource);
|
||||
mipped_program.info.images.push_back(mipped_storage_resource);
|
||||
mipped_program.info.images.push_back(storage_resource);
|
||||
@@ -14933,7 +14965,7 @@ public:
|
||||
mipped_storage_descriptor,
|
||||
overwide_mipped_storage_descriptor,
|
||||
overwide_mipped_storage_descriptor};
|
||||
ShaderStageRuntime mipped_runtime{&mipped_program, &mipped_snapshot};
|
||||
ShaderStageRuntime mipped_runtime{&mipped_module, &mipped_snapshot};
|
||||
mipped_prepared.runtime = &mipped_runtime;
|
||||
mipped_prepared.images.push_back(
|
||||
std::move(plain_mipped_storage_binding));
|
||||
@@ -15114,7 +15146,8 @@ public:
|
||||
views[2] != views[3] && views[1] == views.back(),
|
||||
"different texture clamps aliased or identical clamped views "
|
||||
"were not reused");
|
||||
ShaderRecompiler::IR::CompiledShaderInfo gather_info{};
|
||||
ShaderModule gather_module;
|
||||
auto &gather_info = gather_module.info;
|
||||
gather_info.stage = ShaderType::Compute;
|
||||
gather_info.info = lod_program.program.info;
|
||||
gather_info.info.images[0].mip_mode =
|
||||
@@ -15122,7 +15155,7 @@ public:
|
||||
gather_info.info.images[0].mip_count = 4;
|
||||
auto gather_snapshot = lod_program.resources;
|
||||
gather_snapshot.images[0] = lod_descriptor;
|
||||
ShaderStageRuntime gather_runtime{&gather_info, &gather_snapshot};
|
||||
ShaderStageRuntime gather_runtime{&gather_module, &gather_snapshot};
|
||||
PreparedBindings gather_bindings;
|
||||
executor.PrepareBindings(gather_runtime, gather_bindings);
|
||||
executor.RebindImages(gather_bindings);
|
||||
@@ -15277,11 +15310,12 @@ public:
|
||||
|
||||
ShaderRecompiler::IR::ResourceSnapshot storage_snapshot{};
|
||||
storage_snapshot.images.push_back(storage_descriptor);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo storage_info{};
|
||||
ShaderModule storage_module;
|
||||
auto &storage_info = storage_module.info;
|
||||
storage_info.stage = storage_program.stage;
|
||||
storage_info.info = std::move(storage_program.info);
|
||||
storage_info.bindings = std::move(storage_program.bindings);
|
||||
ShaderStageRuntime storage_runtime{&storage_info, &storage_snapshot};
|
||||
ShaderStageRuntime storage_runtime{&storage_module, &storage_snapshot};
|
||||
PreparedBindings storage_discovery;
|
||||
executor.PrepareBindings(storage_runtime, storage_discovery);
|
||||
const auto storage_id = storage_discovery.images[0].image_id;
|
||||
@@ -15308,11 +15342,12 @@ public:
|
||||
set_image_bindings(sampled_program);
|
||||
ShaderRecompiler::IR::ResourceSnapshot sampled_snapshot{};
|
||||
sampled_snapshot.images.push_back(storage_descriptor);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo sampled_info{};
|
||||
ShaderModule sampled_module;
|
||||
auto &sampled_info = sampled_module.info;
|
||||
sampled_info.stage = sampled_program.stage;
|
||||
sampled_info.info = std::move(sampled_program.info);
|
||||
sampled_info.bindings = std::move(sampled_program.bindings);
|
||||
ShaderStageRuntime sampled_runtime{&sampled_info, &sampled_snapshot};
|
||||
ShaderStageRuntime sampled_runtime{&sampled_module, &sampled_snapshot};
|
||||
|
||||
constexpr uint64_t ordered_sampled_address = base + 0x10000;
|
||||
const uint32_t ordered_sampled_value = 0x89abcdefu;
|
||||
@@ -15332,7 +15367,7 @@ public:
|
||||
ordered_descriptor.dword_count = 8;
|
||||
ShaderRecompiler::IR::ResourceSnapshot ordered_snapshot{};
|
||||
ordered_snapshot.images.push_back(ordered_descriptor);
|
||||
ShaderStageRuntime ordered_sampled_runtime{sampled_runtime.program,
|
||||
ShaderStageRuntime ordered_sampled_runtime{sampled_runtime.module,
|
||||
&ordered_snapshot};
|
||||
auto ordered_bindings = RenderExecutorTestAccess::PrepareGraphicsBindings(
|
||||
executor, storage_runtime, ordered_sampled_runtime, true);
|
||||
@@ -15387,23 +15422,25 @@ public:
|
||||
vertex_sampled_program.resource_tracking_complete = true;
|
||||
vertex_sampled_program.info.images.push_back(sampled_resource);
|
||||
set_image_bindings(vertex_sampled_program);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo vertex_sampled_info{};
|
||||
ShaderModule vertex_sampled_module;
|
||||
auto &vertex_sampled_info = vertex_sampled_module.info;
|
||||
vertex_sampled_info.stage = vertex_sampled_program.stage;
|
||||
vertex_sampled_info.info = std::move(vertex_sampled_program.info);
|
||||
vertex_sampled_info.bindings =
|
||||
std::move(vertex_sampled_program.bindings);
|
||||
ShaderStageRuntime vertex_sampled_runtime{
|
||||
&vertex_sampled_info, sampled_runtime.resources};
|
||||
&vertex_sampled_module, sampled_runtime.resources};
|
||||
ShaderRecompiler::IR::Program pixel_storage_program{};
|
||||
pixel_storage_program.stage = ShaderType::Pixel;
|
||||
pixel_storage_program.resource_tracking_complete = true;
|
||||
pixel_storage_program.info.images.push_back(storage_resource);
|
||||
set_image_bindings(pixel_storage_program);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo pixel_storage_info{};
|
||||
ShaderModule pixel_storage_module;
|
||||
auto &pixel_storage_info = pixel_storage_module.info;
|
||||
pixel_storage_info.stage = pixel_storage_program.stage;
|
||||
pixel_storage_info.info = std::move(pixel_storage_program.info);
|
||||
pixel_storage_info.bindings = std::move(pixel_storage_program.bindings);
|
||||
ShaderStageRuntime pixel_storage_runtime{&pixel_storage_info,
|
||||
ShaderStageRuntime pixel_storage_runtime{&pixel_storage_module,
|
||||
storage_runtime.resources};
|
||||
auto writable_alias_bindings =
|
||||
RenderExecutorTestAccess::PrepareGraphicsBindings(
|
||||
@@ -15476,13 +15513,14 @@ public:
|
||||
split_ir.resource_tracking_complete = true;
|
||||
split_ir.info.images = {storage_resource, sampled_resource};
|
||||
set_image_bindings(split_ir);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo split_program{};
|
||||
ShaderModule split_module;
|
||||
auto &split_program = split_module.info;
|
||||
split_program.stage = split_ir.stage;
|
||||
split_program.info = std::move(split_ir.info);
|
||||
split_program.bindings = std::move(split_ir.bindings);
|
||||
PreparedBindings split_bindings{};
|
||||
ShaderRecompiler::IR::ResourceSnapshot split_snapshot;
|
||||
ShaderStageRuntime split_runtime{&split_program, &split_snapshot};
|
||||
ShaderStageRuntime split_runtime{&split_module, &split_snapshot};
|
||||
split_bindings.runtime = &split_runtime;
|
||||
split_bindings.images.push_back(
|
||||
{split_id, texture_cache.FindTexture(split_id, split_storage_desc),
|
||||
@@ -15569,12 +15607,13 @@ public:
|
||||
depth_views_ir.resource_tracking_complete = true;
|
||||
depth_views_ir.info.images = {sampled_resource, sampled_resource};
|
||||
set_image_bindings(depth_views_ir);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo depth_views_program{};
|
||||
ShaderModule depth_views_module;
|
||||
auto &depth_views_program = depth_views_module.info;
|
||||
depth_views_program.stage = depth_views_ir.stage;
|
||||
depth_views_program.info = std::move(depth_views_ir.info);
|
||||
depth_views_program.bindings = std::move(depth_views_ir.bindings);
|
||||
ShaderRecompiler::IR::ResourceSnapshot depth_views_snapshot;
|
||||
ShaderStageRuntime depth_views_runtime{&depth_views_program, &depth_views_snapshot};
|
||||
ShaderStageRuntime depth_views_runtime{&depth_views_module, &depth_views_snapshot};
|
||||
PreparedBindings depth_views_binding{};
|
||||
depth_views_binding.runtime = &depth_views_runtime;
|
||||
depth_views_binding.images.push_back(
|
||||
@@ -15909,8 +15948,8 @@ public:
|
||||
registers.SetDepthClearValue(0.375f);
|
||||
ShaderRecompiler::IR::ResourceSnapshot bounds_snapshot;
|
||||
bounds_snapshot.images.push_back(sampled_depth_value);
|
||||
ShaderStageRuntime bounds_vertex{&vertex_sampled_info, &bounds_snapshot};
|
||||
ShaderStageRuntime bounds_pixel{&sampled_info, &bounds_snapshot};
|
||||
ShaderStageRuntime bounds_vertex{&vertex_sampled_module, &bounds_snapshot};
|
||||
ShaderStageRuntime bounds_pixel{&sampled_module, &bounds_snapshot};
|
||||
const auto depth_texels = depth_only.desc.info.extent.width *
|
||||
depth_only.desc.info.extent.height;
|
||||
const auto depth_bytes = depth_texels * sizeof(uint32_t);
|
||||
@@ -16326,9 +16365,9 @@ public:
|
||||
shared_depth_value.dword_count = 8;
|
||||
ShaderRecompiler::IR::ResourceSnapshot shared_depth_snapshot;
|
||||
shared_depth_snapshot.images.push_back(shared_depth_value);
|
||||
ShaderStageRuntime shared_depth_vertex{&vertex_sampled_info,
|
||||
ShaderStageRuntime shared_depth_vertex{&vertex_sampled_module,
|
||||
&shared_depth_snapshot};
|
||||
ShaderStageRuntime shared_depth_pixel{&sampled_info,
|
||||
ShaderStageRuntime shared_depth_pixel{&sampled_module,
|
||||
&shared_depth_snapshot};
|
||||
for (const bool stencil_write : {true, false}) {
|
||||
registers.SetDepthRenderTarget(phased_depth_target);
|
||||
@@ -16500,7 +16539,8 @@ public:
|
||||
(static_cast<uint32_t>(Prospero::ImageType::kColor2DArray) << 28u);
|
||||
array_texture.fields[4] = 1;
|
||||
|
||||
ShaderRecompiler::IR::CompiledShaderInfo array_program{};
|
||||
ShaderModule array_module;
|
||||
auto &array_program = array_module.info;
|
||||
array_program.stage = ShaderType::Compute;
|
||||
ShaderRecompiler::IR::ImageResource array_resource{};
|
||||
array_resource.resource_class =
|
||||
@@ -16517,7 +16557,7 @@ public:
|
||||
array_descriptor.dword_count = 8;
|
||||
ShaderRecompiler::IR::ResourceSnapshot array_snapshot{};
|
||||
array_snapshot.images.push_back(array_descriptor);
|
||||
ShaderStageRuntime array_runtime{&array_program, &array_snapshot};
|
||||
ShaderStageRuntime array_runtime{&array_module, &array_snapshot};
|
||||
|
||||
PreparedBindings array_binding;
|
||||
executor.PrepareBindings(array_runtime, array_binding);
|
||||
@@ -16684,7 +16724,8 @@ public:
|
||||
std::end(colliding_msaa_texture.fields),
|
||||
colliding_msaa_descriptor.dwords.begin());
|
||||
colliding_msaa_descriptor.dword_count = 8;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo colliding_msaa_program{};
|
||||
ShaderModule colliding_msaa_module;
|
||||
auto &colliding_msaa_program = colliding_msaa_module.info;
|
||||
colliding_msaa_program.stage = ShaderType::Compute;
|
||||
auto colliding_msaa_resource = array_resource;
|
||||
colliding_msaa_resource.dimension =
|
||||
@@ -16693,7 +16734,7 @@ public:
|
||||
ShaderRecompiler::IR::ResourceSnapshot colliding_msaa_snapshot{};
|
||||
colliding_msaa_snapshot.images.push_back(colliding_msaa_descriptor);
|
||||
ShaderStageRuntime colliding_msaa_runtime{
|
||||
&colliding_msaa_program, &colliding_msaa_snapshot};
|
||||
&colliding_msaa_module, &colliding_msaa_snapshot};
|
||||
PreparedBindings colliding_msaa_binding;
|
||||
executor.PrepareBindings(colliding_msaa_runtime, colliding_msaa_binding);
|
||||
executor.RebindImages(colliding_msaa_binding);
|
||||
@@ -16744,7 +16785,8 @@ public:
|
||||
std::copy(std::begin(msaa_texture.fields), std::end(msaa_texture.fields),
|
||||
msaa_descriptor.dwords.begin());
|
||||
msaa_descriptor.dword_count = 8;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo msaa_program{};
|
||||
ShaderModule msaa_module;
|
||||
auto &msaa_program = msaa_module.info;
|
||||
msaa_program.stage = ShaderType::Compute;
|
||||
auto msaa_resource = array_resource;
|
||||
msaa_resource.dimension =
|
||||
@@ -16752,7 +16794,7 @@ public:
|
||||
msaa_program.info.images.push_back(msaa_resource);
|
||||
ShaderRecompiler::IR::ResourceSnapshot msaa_snapshot{};
|
||||
msaa_snapshot.images.push_back(msaa_descriptor);
|
||||
ShaderStageRuntime msaa_runtime{&msaa_program, &msaa_snapshot};
|
||||
ShaderStageRuntime msaa_runtime{&msaa_module, &msaa_snapshot};
|
||||
PreparedBindings msaa_binding;
|
||||
executor.PrepareBindings(msaa_runtime, msaa_binding);
|
||||
executor.RebindImages(msaa_binding);
|
||||
@@ -16784,7 +16826,8 @@ public:
|
||||
std::end(msaa_array_texture.fields),
|
||||
msaa_array_descriptor.dwords.begin());
|
||||
msaa_array_descriptor.dword_count = 8;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo msaa_array_program{};
|
||||
ShaderModule msaa_array_module;
|
||||
auto &msaa_array_program = msaa_array_module.info;
|
||||
msaa_array_program.stage = ShaderType::Compute;
|
||||
auto msaa_array_resource = array_resource;
|
||||
msaa_array_resource.dimension =
|
||||
@@ -16792,7 +16835,7 @@ public:
|
||||
msaa_array_program.info.images.push_back(msaa_array_resource);
|
||||
ShaderRecompiler::IR::ResourceSnapshot msaa_array_snapshot{};
|
||||
msaa_array_snapshot.images.push_back(msaa_array_descriptor);
|
||||
ShaderStageRuntime msaa_array_runtime{&msaa_array_program, &msaa_array_snapshot};
|
||||
ShaderStageRuntime msaa_array_runtime{&msaa_array_module, &msaa_array_snapshot};
|
||||
PreparedBindings msaa_array_binding;
|
||||
executor.PrepareBindings(msaa_array_runtime, msaa_array_binding);
|
||||
executor.RebindImages(msaa_array_binding);
|
||||
@@ -17033,7 +17076,8 @@ public:
|
||||
DstSel(4, 5, 6, 7) | (static_cast<uint32_t>(linear) << 20u) |
|
||||
(static_cast<uint32_t>(Prospero::ImageType::kColor2D) << 28u);
|
||||
|
||||
ShaderRecompiler::IR::CompiledShaderInfo program{};
|
||||
ShaderModule module;
|
||||
auto &program = module.info;
|
||||
program.stage = ShaderType::Compute;
|
||||
ShaderRecompiler::IR::ImageResource stencil_resource{};
|
||||
stencil_resource.resource_class =
|
||||
@@ -17050,7 +17094,7 @@ public:
|
||||
descriptor.dwords.begin());
|
||||
descriptor.dword_count = 8;
|
||||
snapshot.images.push_back(descriptor);
|
||||
ShaderStageRuntime runtime{&program, &snapshot};
|
||||
ShaderStageRuntime runtime{&module, &snapshot};
|
||||
|
||||
PreparedBindings prepared;
|
||||
context.GetRenderExecutor().PrepareBindings(runtime, prepared);
|
||||
@@ -17139,10 +17183,10 @@ public:
|
||||
"captured stencil shader could not resolve its clear byte");
|
||||
ShaderRecompiler::IR::ApplyResourceSpecialization(stencil_translated.program,
|
||||
stencil_specialization);
|
||||
ShaderRecompiler::IR::CompiledShaderInfo stencil_program{};
|
||||
stencil_program.stage = ShaderType::Compute;
|
||||
stencil_program.info = std::move(stencil_translated.program.info);
|
||||
stencil_compute.stage.program = &stencil_program;
|
||||
ShaderModule stencil_program;
|
||||
stencil_program.info.stage = ShaderType::Compute;
|
||||
stencil_program.info.info = std::move(stencil_translated.program.info);
|
||||
stencil_compute.stage.module = &stencil_program;
|
||||
vk::ClearValue stencil_initial{};
|
||||
stencil_initial.depthStencil = vk::ClearDepthStencilValue{0.625f, 0x91};
|
||||
TextureCacheTestAccess::ClearImage(texture_cache, scheduler.Current(), depth_id,
|
||||
@@ -18294,19 +18338,20 @@ public:
|
||||
AppendEnd(&test.fragment_code);
|
||||
auto fragment = CompileFragmentCase(test);
|
||||
const auto vertex_spirv = TestSpv::MakePassthroughVertexSpirv(false);
|
||||
ShaderProgram vertex_shader{1, CreateShaderModule(name, vertex_spirv)};
|
||||
ShaderProgram pixel_shader{2, CreateShaderModule(name, fragment.spirv)};
|
||||
ShaderRecompiler::IR::CompiledShaderInfo vertex_program{};
|
||||
vertex_program.stage = ShaderType::Vertex;
|
||||
vertex_program.info.vertex_fetch_components[0] = 2;
|
||||
vertex_program.info.vertex_fetch_components[1] = packed_vertex_color ? 3 : 4;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo pixel_program{};
|
||||
pixel_program.stage = ShaderType::Pixel;
|
||||
pixel_program.info = fragment.program.info;
|
||||
pixel_program.bindings = fragment.program.bindings;
|
||||
ShaderModule vertex_shader{.id = 1, .module = CreateShaderModule(name, vertex_spirv)};
|
||||
vertex_shader.info.stage = ShaderType::Vertex;
|
||||
vertex_shader.info.info.vertex_fetch_components[0] = 2;
|
||||
vertex_shader.info.info.vertex_fetch_components[1] = packed_vertex_color ? 3 : 4;
|
||||
// No narrower host format covers the components the stage reads from either attribute.
|
||||
vertex_shader.vertex_formats = {VulkanFormat(Prospero::BufferFormat::k32_32Float),
|
||||
VulkanFormat(color_format)};
|
||||
ShaderModule pixel_shader{.id = 2, .module = CreateShaderModule(name, fragment.spirv)};
|
||||
pixel_shader.info.stage = ShaderType::Pixel;
|
||||
pixel_shader.info.info = fragment.program.info;
|
||||
pixel_shader.info.bindings = fragment.program.bindings;
|
||||
ShaderVertexInputInfo vertex{};
|
||||
ShaderRecompiler::IR::ResourceSnapshot vertex_snapshot;
|
||||
vertex.stage.program = &vertex_program;
|
||||
vertex.stage.module = &vertex_shader;
|
||||
vertex.stage.resources = &vertex_snapshot;
|
||||
vertex.resources_num = 2;
|
||||
vertex.buffers_num = 1;
|
||||
@@ -18317,10 +18362,10 @@ public:
|
||||
vertex.resources[i].fields[3] = DstSel(4, 5, 6, 7) |
|
||||
(static_cast<uint32_t>(format) << 12u);
|
||||
vertex.resources_dst[i].registers_num =
|
||||
i == 0 ? 2 : vertex_program.info.vertex_fetch_components[1];
|
||||
i == 0 ? 2 : vertex_shader.info.info.vertex_fetch_components[1];
|
||||
}
|
||||
ShaderPixelInputInfo pixel{};
|
||||
pixel.stage.program = &pixel_program;
|
||||
pixel.stage.module = &pixel_shader;
|
||||
pixel.stage.resources = &fragment.resources;
|
||||
|
||||
RenderColorInfo color{};
|
||||
@@ -18368,8 +18413,6 @@ public:
|
||||
DrawRenderState state{.depth_info = depth, .color_info = {color}, .color_count = 1,
|
||||
.topology = topology, .ps_active = true,
|
||||
.vertex_info = {vertex}, .ps_input_info = pixel};
|
||||
state.vertex_info[0].stage.handle = &vertex_shader;
|
||||
state.ps_input_info.stage.handle = &pixel_shader;
|
||||
return context.GetPipelineCache().GetGraphicsPipeline(scheduler.Current(), state);
|
||||
};
|
||||
auto &filled = pipeline(true, 2, 2);
|
||||
@@ -18723,8 +18766,6 @@ public:
|
||||
.code_size_bytes = static_cast<uint32_t>(native_pixel.size() * sizeof(u32))});
|
||||
shaders.SetEsShaderBase(vertex_address);
|
||||
shaders.SetPsShaderBase(pixel_address);
|
||||
const auto owned_vertex_shader = vertex_shader;
|
||||
const auto owned_pixel_shader = pixel_shader;
|
||||
depth.stencil_test_enable = false;
|
||||
registers.SetViewportTransformControl(0x300);
|
||||
user_config.SetPrimitiveType(Prospero::PrimitiveType::kTriList);
|
||||
@@ -18738,8 +18779,6 @@ public:
|
||||
const auto native = refresh();
|
||||
vertex = native.vertex_info[0];
|
||||
pixel = native.ps_input_info;
|
||||
vertex_shader = *vertex.stage.handle;
|
||||
pixel_shader = *pixel.stage.handle;
|
||||
};
|
||||
const auto silent = refresh();
|
||||
registers.SetDepthShaderControl({.shader_kill_enable = true});
|
||||
@@ -18763,7 +18802,7 @@ public:
|
||||
depth_writing.ps_active && depth_writing.mrt_mask == 0 &&
|
||||
writing.ps_active && writing.mrt_mask == 1u && partial.mrt_mask == 1u &&
|
||||
writing.VertexStages().size() == 1 &&
|
||||
writing.vertex_info[0].stage.handle != nullptr,
|
||||
writing.vertex_info[0].stage.module != nullptr,
|
||||
"pixel activity or its MRT mask ignored the color outputs or depth side effects");
|
||||
std::array<uint64_t, 2> wave_ids{};
|
||||
std::array<std::vector<u32>, 2> wave_keys;
|
||||
@@ -18774,17 +18813,17 @@ public:
|
||||
registers.SetPsInControl(wave.control);
|
||||
native_programs();
|
||||
Require(name, "pixel wave metadata propagation",
|
||||
pixel.input_num == 8 && pixel.stage.program->wave_size == wave.width,
|
||||
pixel.input_num == 8 && pixel.stage.module->info.wave_size == wave.width,
|
||||
"SPI_PS_IN_CONTROL width did not reach the compiled pixel program");
|
||||
const auto index = static_cast<uint32_t>(wave.width == 32);
|
||||
std::vector<u32> key;
|
||||
BuildStageStaticKey(pixel, key);
|
||||
if (wave_ids[index] != 0) {
|
||||
Require(name, "pixel wave cache reuse",
|
||||
pixel_shader.id == wave_ids[index] && key == wave_keys[index],
|
||||
pixel.stage.module->id == wave_ids[index] && key == wave_keys[index],
|
||||
"restoring wave64 did not reuse its original program");
|
||||
}
|
||||
wave_ids[index] = pixel_shader.id;
|
||||
wave_ids[index] = pixel.stage.module->id;
|
||||
wave_keys[index] = std::move(key);
|
||||
draw(pipeline(true, 2, 2));
|
||||
const auto wave_pixels = read_color();
|
||||
@@ -18832,8 +18871,8 @@ public:
|
||||
(wave == 32u ? 0x00400000u : 0u));
|
||||
native_programs();
|
||||
Require(name, "native NGG waterfall wave",
|
||||
vertex.stage.program->stage == ShaderType::Vertex &&
|
||||
vertex.stage.program->wave_size == wave,
|
||||
vertex.stage.module->info.stage == ShaderType::Vertex &&
|
||||
vertex.stage.module->info.wave_size == wave,
|
||||
"NGG waterfall bypassed the native vertex path or lost its guest wave width");
|
||||
for (const u32 count : {3u, 6u, 33u}) {
|
||||
draw(pipeline(true, 2, 2), count);
|
||||
@@ -18907,10 +18946,10 @@ public:
|
||||
auto &selected = pipeline(true, 2, 2);
|
||||
if (test.mode == ShaderAlphaBlendSource::SourceAlpha) {
|
||||
Require(name, "equal blend equation cache reuse",
|
||||
broadcast_program == 0 || (pixel_shader.id == broadcast_program &&
|
||||
broadcast_program == 0 || (pixel.stage.module->id == broadcast_program &&
|
||||
selected.pipeline == broadcast_pipeline),
|
||||
"equivalent separate alpha state created another shader or pipeline");
|
||||
broadcast_program = pixel_shader.id;
|
||||
broadcast_program = pixel.stage.module->id;
|
||||
broadcast_pipeline = selected.pipeline;
|
||||
}
|
||||
constexpr std::array<float, 4> destination{0.3f, 0.3f, 0.1f, 0.2f};
|
||||
@@ -19333,6 +19372,13 @@ public:
|
||||
check("auto embedded fetch", fetch_vs, false, 4);
|
||||
check("indexed native fetch", vertex_address, true, 2);
|
||||
check("auto native fetch", vertex_address, false, 6);
|
||||
// Pipelines created from only their key and stage modules draw the same.
|
||||
scheduler.Finish();
|
||||
Require("PipelineFromKey", "vertex input pipelines",
|
||||
PipelineCacheTestAccess::RecreateGraphicsPipelines(context.GetPipelineCache()) > 0,
|
||||
"no cached graphics pipeline named only compiled modules");
|
||||
check("recreated indexed embedded fetch", fetch_vs, true, 0);
|
||||
check("recreated auto native fetch", vertex_address, false, 6);
|
||||
}
|
||||
|
||||
// A fourth VS invocation reads beyond the descriptor instead of reconstructing the corner.
|
||||
@@ -19382,10 +19428,7 @@ public:
|
||||
registers.SetPsInputEna(2);
|
||||
registers.SetPsInputAddr(2);
|
||||
registers.SetPsInputSettings(0, 0);
|
||||
for (const auto primitive : {Prospero::PrimitiveType::kRectList,
|
||||
Prospero::PrimitiveType::kRectListLegacy}) {
|
||||
const char *rect_name = primitive == Prospero::PrimitiveType::kRectList
|
||||
? "RectListThreeRecords" : "LegacyRectListThreeRecords";
|
||||
const auto check_rect = [&](Prospero::PrimitiveType primitive, const char *rect_name) {
|
||||
user_config.SetPrimitiveType(primitive);
|
||||
registers.SetModeControl({});
|
||||
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), sparse_color.image_id,
|
||||
@@ -19409,7 +19452,14 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
check_rect(Prospero::PrimitiveType::kRectList, "RectListThreeRecords");
|
||||
check_rect(Prospero::PrimitiveType::kRectListLegacy, "LegacyRectListThreeRecords");
|
||||
scheduler.Finish();
|
||||
Require("PipelineFromKey", "rectangle-list pipelines",
|
||||
PipelineCacheTestAccess::RecreateGraphicsPipelines(context.GetPipelineCache()) > 0,
|
||||
"no cached graphics pipeline named only compiled modules");
|
||||
check_rect(Prospero::PrimitiveType::kRectList, "PipelineFromKeyRectList");
|
||||
// Captured format30 uses uncompressed mode9 at MRT2. Keep a blended
|
||||
// floating-point MRT live beside it, including sparse export routing.
|
||||
constexpr uint64_t packed_address = depth_address + 0x28000;
|
||||
@@ -19516,9 +19566,10 @@ public:
|
||||
"packed conversion or rounding contaminated another MRT or followed a physical slot");
|
||||
if (test.slot == 2) {
|
||||
auto &id = test.truncate ? truncate_program : half_up_program;
|
||||
Require(name, "packed rounding program reuse", id == 0 || id == pixel_shader.id,
|
||||
Require(name, "packed rounding program reuse",
|
||||
id == 0 || id == pixel.stage.module->id,
|
||||
"restoring half-up rounding failed to reuse its program");
|
||||
id = pixel_shader.id;
|
||||
id = pixel.stage.module->id;
|
||||
}
|
||||
RenderColorInfo packed_target{}, float_target{};
|
||||
RenderExecutorTestAccess::ResolveRenderColorTarget(
|
||||
@@ -19576,9 +19627,6 @@ public:
|
||||
DestroyBuffer(&packed_output);
|
||||
m_device.destroySampler(packed_sampler);
|
||||
DestroyBuffer(&stencil_readback);
|
||||
|
||||
vertex_shader = owned_vertex_shader;
|
||||
pixel_shader = owned_pixel_shader;
|
||||
}
|
||||
resources.UnmapMemory(depth_address, allocation_size);
|
||||
scheduler.Finish();
|
||||
@@ -44530,7 +44578,7 @@ void CheckComputeLdsLimit(VulkanHarness &vulkan) {
|
||||
regs.cs_regs.num_thread_z = 1;
|
||||
regs.cs_regs.wave_size = 32;
|
||||
PipelineCache cache(graphics, nullptr);
|
||||
ShaderProgram previous;
|
||||
uint64_t previous_id = 0;
|
||||
uint16_t previous_units = 0;
|
||||
for (const auto units : {static_cast<uint16_t>(limit_units - 1u), limit_units,
|
||||
uint16_t{112}, uint16_t{128}, uint16_t{128}}) {
|
||||
@@ -44544,12 +44592,12 @@ void CheckComputeLdsLimit(VulkanHarness &vulkan) {
|
||||
Require(name, "pipeline creation",
|
||||
cache.GetComputePipeline(input).pipeline != nullptr,
|
||||
"full-size LDS shader did not create a Vulkan compute pipeline");
|
||||
if (previous.id != 0) {
|
||||
if (previous_id != 0) {
|
||||
Require(name, "guest-size cache identity",
|
||||
(program.id == previous.id) == (units == previous_units),
|
||||
(program->id == previous_id) == (units == previous_units),
|
||||
"different LDS sizes shared a shader, or repeating a size recompiled it");
|
||||
}
|
||||
previous = program;
|
||||
previous_id = program->id;
|
||||
previous_units = units;
|
||||
}
|
||||
std::printf("[gpu] %-32s ok\n", name);
|
||||
@@ -44585,7 +44633,7 @@ void CheckStableProgramIds(VulkanHarness &vulkan) {
|
||||
DstSel(4, 5, 6, 7) | (static_cast<u32>(Prospero::BufferFormat::k32UInt) << 12u)}};
|
||||
std::copy_n(buffer.fields, 4, regs.cs_user_sgpr.value);
|
||||
ShaderComputeInputInfo input{};
|
||||
return cache.GetComputeProgram(regs, input).id;
|
||||
return cache.GetComputeProgram(regs, input)->id;
|
||||
};
|
||||
std::array<uint64_t, 3> forward{}, reverse{};
|
||||
{
|
||||
@@ -45283,10 +45331,10 @@ void CheckEmbeddedFetchVertexOffset() {
|
||||
u32 index_offset) {
|
||||
ShaderVertexInputInfo vertex;
|
||||
vertex.fetch_embedded = true;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo program{};
|
||||
program.user_data_base = result.program.user_data_base;
|
||||
program.info.vertex_offset_sgpr = result.program.info.vertex_offset_sgpr;
|
||||
vertex.stage.program = &program;
|
||||
ShaderModule module;
|
||||
module.info.user_data_base = result.program.user_data_base;
|
||||
module.info.info.vertex_offset_sgpr = result.program.info.vertex_offset_sgpr;
|
||||
vertex.stage.module = &module;
|
||||
vertex.stage.resources = &result.resources;
|
||||
return ResolveDrawOffsets(index_offset, vertex).first;
|
||||
};
|
||||
@@ -45294,11 +45342,11 @@ void CheckEmbeddedFetchVertexOffset() {
|
||||
const auto ResolveInstance = [](const CompiledShader &result) {
|
||||
ShaderVertexInputInfo vertex;
|
||||
vertex.fetch_embedded = true;
|
||||
ShaderRecompiler::IR::CompiledShaderInfo program{};
|
||||
program.user_data_base = result.program.user_data_base;
|
||||
program.info.instance_offset_sgpr =
|
||||
ShaderModule module;
|
||||
module.info.user_data_base = result.program.user_data_base;
|
||||
module.info.info.instance_offset_sgpr =
|
||||
result.program.info.instance_offset_sgpr;
|
||||
vertex.stage.program = &program;
|
||||
vertex.stage.module = &module;
|
||||
vertex.stage.resources = &result.resources;
|
||||
return ResolveDrawOffsets(0, vertex).second;
|
||||
};
|
||||
@@ -47924,17 +47972,17 @@ void CheckDynamicRenderingState() {
|
||||
Require("DynamicRenderingState", "layout identity", first != changed,
|
||||
"attachment layout did not participate in rendering identity");
|
||||
|
||||
PipelineRenderingState rgba{};
|
||||
rgba.color_count = 1;
|
||||
rgba.color_formats[0] = vk::Format::eR8G8B8A8Unorm;
|
||||
GraphicsPipelineKey rgba{};
|
||||
rgba.rendering.color_count = 1;
|
||||
rgba.rendering.color_formats[0] = vk::Format::eR8G8B8A8Unorm;
|
||||
auto uint_color = rgba;
|
||||
uint_color.color_formats[0] = vk::Format::eR8G8B8A8Uint;
|
||||
uint_color.rendering.color_formats[0] = vk::Format::eR8G8B8A8Uint;
|
||||
Require("DynamicRenderingState", "pipeline color format identity",
|
||||
rgba != uint_color,
|
||||
"distinct dynamic-rendering formats can alias one pipeline key");
|
||||
auto depth = rgba;
|
||||
depth.depth_format = vk::Format::eD32SfloatS8Uint;
|
||||
depth.stencil_format = vk::Format::eD32SfloatS8Uint;
|
||||
depth.rendering.depth_format = vk::Format::eD32SfloatS8Uint;
|
||||
depth.rendering.stencil_format = vk::Format::eD32SfloatS8Uint;
|
||||
Require("DynamicRenderingState", "pipeline depth/stencil identity",
|
||||
rgba != depth,
|
||||
"depth/stencil formats did not participate in pipeline identity");
|
||||
|
||||
Reference in New Issue
Block a user