graphics: store vertex attribute bindings without duplicated arrays

This commit is contained in:
nmzik
2026-09-29 03:25:22 +04:00
parent 8e42e99788
commit b43bf9f7fb
6 changed files with 115 additions and 79 deletions
+1 -3
View File
@@ -14062,9 +14062,7 @@ public:
vertex.resources_num = 2;
vertex.buffers_num = 1;
vertex.buffers[0].stride = 6 * sizeof(float);
vertex.buffers[0].attr_num = 2;
vertex.buffers[0].attr_indices[1] = 1;
vertex.buffers[0].attr_offsets[1] = 2 * sizeof(float);
vertex.resources[1].UpdateAddress48(2 * sizeof(float));
for (uint32_t i = 0; i < 2; i++) {
const auto format = i == 0 ? Prospero::BufferFormat::k32_32Float
: packed_vertex_color ? Prospero::BufferFormat::k11_11_10Float
+57 -3
View File
@@ -1702,6 +1702,61 @@ void TestShaderStageBarriers() {
"independent vertex invocations retained a workgroup barrier");
}
void TestVertexBufferGrouping() {
const uint32_t shader[] = {EncodeSopp(0x01)};
std::array<uint16_t, static_cast<size_t>(AgcDirectResourceType::Last) + 1> offsets;
offsets.fill(AGC_ILLEGAL_DIRECT_OFFSET);
offsets[static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] = 0;
offsets[static_cast<size_t>(AgcDirectResourceType::PtrVertexAttribDescTable)] = 2;
ShaderUserData user_data{};
user_data.direct_resource_count = offsets.size();
user_data.direct_resource_offset = offsets.data();
std::array<ShaderSemantic, 4> semantics{};
for (uint32_t i = 0; i < semantics.size(); i++) {
semantics[i].semantic = i;
semantics[i].hardware_mapping = i;
semantics[i].size_in_elements = 1;
}
ShaderMappedData mapped{};
mapped.user_data = &user_data;
mapped.code_size_bytes = sizeof(shader);
mapped.input_semantics = semantics.data();
mapped.num_input_semantics = semantics.size();
HW::VertexShaderInfo regs{};
regs.es_regs.data_addr = reinterpret_cast<uint64_t>(shader);
regs.gs_regs.rsrc2.user_sgpr = 4;
ShaderMapUserData(regs.es_regs.data_addr, mapped);
std::array<ShaderBufferResource, 4> descriptors{};
const std::array<uint32_t, 4> attributes{0, 1u | (1u << 26u), 2, 3};
const std::array<uint64_t, 2> pointers{
reinterpret_cast<uint64_t>(descriptors.data()),
reinterpret_cast<uint64_t>(attributes.data())};
std::memcpy(regs.gs_user_sgpr.value, pointers.data(), sizeof(pointers));
ShaderVertexInputInfo input{};
for (const uint64_t base : {0x1000u, 0x3000u}) {
for (auto &descriptor : descriptors) {
descriptor.fields[1] = 16u << 16u;
descriptor.fields[2] = 8;
descriptor.UpdateAddress48(base);
}
descriptors[0].UpdateAddress48(base + 8);
descriptors[1].UpdateAddress48(base + 4);
descriptors[3].fields[1] = 0; // Constant attributes use their own buffer.
(void)PrepareProgram(regs, HW::Context{}, HW::UserConfig{}, input);
Check(input.resources_num == 4 && input.buffers_num == 3 &&
input.resources_dst[0].buffer_index == 0 &&
input.resources_dst[1].buffer_index == 1 &&
input.resources_dst[2].buffer_index == 0 &&
input.resources_dst[3].buffer_index == 2,
"interleaved vertex attributes lost their stride or instance-rate binding");
Check(input.buffers[0].addr == base && input.buffers[1].addr == base + 4 &&
input.buffers[1].fetch_index == 1 && input.buffers[2].stride == 0 &&
input.resources[0].Base48() - input.buffers[0].addr == 8 &&
input.resources[2].Base48() == input.buffers[0].addr,
"a later lower-address attribute or changed table left stale vertex offsets");
}
}
void TestNggVertexEntryState() {
using namespace ShaderRecompiler;
// PPSA03309 shader 5a39eb2021a5d2c1: retain its NGG prologue and replace
@@ -10571,13 +10626,11 @@ void TestNewShaderRecompilerClipDisabledPosition() {
ShaderVertexInputInfo layout_a{};
layout_a.resources_num = 1;
layout_a.buffers_num = 1;
layout_a.buffers[0].attr_num = 1;
layout_a.buffers[0].attr_indices[0] = 0;
layout_a.buffers[0].stride = 16;
auto layout_b = layout_a;
layout_b.buffers[0].stride = 32;
layout_b.buffers[0].fetch_index = 1;
layout_b.buffers[0].attr_offsets[0] = 4;
layout_b.resources[0].UpdateAddress48(4);
Check(MakeStageStaticKey(layout_a) == MakeStageStaticKey(layout_b),
"pipeline-only vertex layout fragmented the shader module cache key");
}
@@ -13855,6 +13908,7 @@ int main() {
TestDemandDrivenSpirvDeclarations();
TestNewShaderRecompilerSMovB32();
TestShaderStageBarriers();
TestVertexBufferGrouping();
TestNggVertexEntryState();
TestNewShaderRecompilerClipDisabledPosition();
TestNewShaderRecompilerAuxPositionExports();