Implement vertex swizzle

This commit is contained in:
nmzik
2026-07-18 03:36:09 +02:00
parent 18479daabd
commit f4b52cea2b
10 changed files with 282 additions and 195 deletions
+98 -61
View File
@@ -9,85 +9,122 @@ namespace {
using namespace Libs::Graphics;
void Check(bool value, const char* text) {
if (!value) {
std::fprintf(stderr, "ShaderVertexMetadataTests: failed: %s\n", text);
std::abort();
}
void Check(bool value, const char *text) {
if (!value) {
std::fprintf(stderr, "ShaderVertexMetadataTests: failed: %s\n", text);
std::abort();
}
}
struct Fixture {
std::array<uint16_t, static_cast<size_t>(AgcDirectResourceType::Last) + 1> offsets {};
ShaderUserData user_data {};
ShaderSemantic semantic {};
ShaderMappedData mapped {};
std::array<uint16_t, static_cast<size_t>(AgcDirectResourceType::Last) + 1>
offsets{};
ShaderUserData user_data{};
ShaderSemantic semantic{};
ShaderMappedData mapped{};
Fixture() {
offsets.fill(AGC_ILLEGAL_DIRECT_OFFSET);
offsets[static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] = 2;
offsets[static_cast<size_t>(AgcDirectResourceType::PtrVertexAttribDescTable)] = 4;
user_data.direct_resource_offset = offsets.data();
user_data.direct_resource_count = static_cast<uint16_t>(offsets.size());
mapped.user_data = &user_data;
mapped.input_semantics = &semantic;
mapped.num_input_semantics = 1;
}
Fixture() {
offsets.fill(AGC_ILLEGAL_DIRECT_OFFSET);
offsets[static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] =
2;
offsets[static_cast<size_t>(
AgcDirectResourceType::PtrVertexAttribDescTable)] = 4;
user_data.direct_resource_offset = offsets.data();
user_data.direct_resource_count = static_cast<uint16_t>(offsets.size());
mapped.user_data = &user_data;
mapped.input_semantics = &semantic;
mapped.num_input_semantics = 1;
}
};
void CheckRejected(const ShaderMappedData& data, const char* text) {
ShaderVertexMetadata output;
output.vertex_buffer_reg = 37;
output.vertex_attrib_reg = 41;
output.input_semantics_count = 7;
std::string error;
Check(!ShaderReadVertexMetadata(data, 64, &output, &error), text);
Check(!error.empty(), "metadata rejection omitted its diagnostic");
Check(output.vertex_buffer_reg == 37 && output.vertex_attrib_reg == 41 &&
output.input_semantics_count == 7,
"metadata rejection changed the prior output");
void CheckRejected(const ShaderMappedData &data, const char *text) {
ShaderVertexMetadata output;
output.vertex_buffer_reg = 37;
output.vertex_attrib_reg = 41;
output.input_semantics_count = 7;
std::string error;
Check(!ShaderReadVertexMetadata(data, 64, &output, &error), text);
Check(!error.empty(), "metadata rejection omitted its diagnostic");
Check(output.vertex_buffer_reg == 37 && output.vertex_attrib_reg == 41 &&
output.input_semantics_count == 7,
"metadata rejection changed the prior output");
}
void TestValidAndInvalidMetadata() {
Fixture fixture;
ShaderVertexMetadata output;
std::string error;
Check(ShaderReadVertexMetadata(fixture.mapped, 64, &output, &error),
"valid AGC vertex metadata was rejected");
Check(output.vertex_buffer_reg == 2 && output.vertex_attrib_reg == 4 &&
output.input_semantics_count == 1,
"valid AGC vertex metadata was decoded incorrectly");
Fixture fixture;
ShaderVertexMetadata output;
std::string error;
Check(ShaderReadVertexMetadata(fixture.mapped, 64, &output, &error),
"valid AGC vertex metadata was rejected");
Check(output.vertex_buffer_reg == 2 && output.vertex_attrib_reg == 4 &&
output.input_semantics_count == 1,
"valid AGC vertex metadata was decoded incorrectly");
auto missing_header = fixture.mapped;
missing_header.user_data = nullptr;
CheckRejected(missing_header, "missing AGC user-data header was accepted");
auto missing_header = fixture.mapped;
missing_header.user_data = nullptr;
CheckRejected(missing_header, "missing AGC user-data header was accepted");
Fixture missing_offsets;
missing_offsets.user_data.direct_resource_offset = nullptr;
CheckRejected(missing_offsets.mapped, "missing direct-resource offsets were accepted");
Fixture missing_offsets;
missing_offsets.user_data.direct_resource_offset = nullptr;
CheckRejected(missing_offsets.mapped,
"missing direct-resource offsets were accepted");
Fixture excessive_resources;
excessive_resources.user_data.direct_resource_count =
static_cast<uint16_t>(excessive_resources.offsets.size() + 1);
CheckRejected(excessive_resources.mapped, "excessive direct-resource count was accepted");
Fixture excessive_resources;
excessive_resources.user_data.direct_resource_count =
static_cast<uint16_t>(excessive_resources.offsets.size() + 1);
CheckRejected(excessive_resources.mapped,
"excessive direct-resource count was accepted");
Fixture excessive_semantics;
excessive_semantics.mapped.num_input_semantics = ShaderVertexInputInfo::RES_MAX + 1;
CheckRejected(excessive_semantics.mapped, "excessive vertex semantic count was accepted");
Fixture excessive_semantics;
excessive_semantics.mapped.num_input_semantics =
ShaderVertexInputInfo::RES_MAX + 1;
CheckRejected(excessive_semantics.mapped,
"excessive vertex semantic count was accepted");
Fixture excessive_register;
excessive_register.offsets[
static_cast<size_t>(AgcDirectResourceType::PtrVertexBufferTable)] = 63;
CheckRejected(excessive_register.mapped, "out-of-domain vertex table SGPR was accepted");
Fixture excessive_register;
excessive_register.offsets[static_cast<size_t>(
AgcDirectResourceType::PtrVertexBufferTable)] = 63;
CheckRejected(excessive_register.mapped,
"out-of-domain vertex table SGPR was accepted");
Fixture missing_semantics;
missing_semantics.mapped.input_semantics = nullptr;
CheckRejected(missing_semantics.mapped, "missing vertex semantic array was accepted");
Fixture missing_semantics;
missing_semantics.mapped.input_semantics = nullptr;
CheckRejected(missing_semantics.mapped,
"missing vertex semantic array was accepted");
}
void TestVertexDstSelectors() {
const auto zero = DecodeVertexDstSelector(0);
const auto one = DecodeVertexDstSelector(1);
Check(zero.kind == VertexDstSelectKind::Zero &&
one.kind == VertexDstSelectKind::One,
"vertex constant selectors were decoded incorrectly");
for (uint8_t selector = 4; selector <= 7; selector++) {
const auto component = DecodeVertexDstSelector(selector);
Check(component.kind == VertexDstSelectKind::Component &&
component.source_component == selector - 4,
"vertex component selector was decoded incorrectly");
}
Check(DecodeVertexDstSelector(2).kind == VertexDstSelectKind::Reserved &&
DecodeVertexDstSelector(3).kind == VertexDstSelectKind::Reserved,
"reserved vertex selectors were accepted");
Check(GetDstSel(DstSel(6, 5, 4, 7), 0) == 6 &&
GetDstSel(DstSel(6, 5, 4, 7), 1) == 5 &&
GetDstSel(DstSel(6, 5, 4, 7), 2) == 4 &&
GetDstSel(DstSel(6, 5, 4, 7), 3) == 7,
"BGRA vertex selector packing was decoded incorrectly");
Check(VertexRawComponentCount(DstSel(7, 0, 0, 0), 1) == 4,
"W-to-X did not widen the raw vertex interface to four components");
Check(VertexRawComponentCount(DstSel(4, 4, 4, 4), 4) == 4 &&
VertexRawComponentCount(DstSel(4, 0, 0, 1), 4) == 4,
"replication or constant selectors changed raw vertex width");
}
} // namespace
int main() {
TestValidAndInvalidMetadata();
std::puts("ShaderVertexMetadataTests: all cases passed");
return 0;
TestValidAndInvalidMetadata();
TestVertexDstSelectors();
std::puts("ShaderVertexMetadataTests: all cases passed");
return 0;
}