From e57c37fa9ce69617b446e80c719608897be53d59 Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 29 Sep 2026 04:27:37 +0400 Subject: [PATCH] graphics: consume vertex semantics directly from shader metadata --- src/graphics/shader/shader.cpp | 10 ++++------ src/graphics/shader/shaderVertexMetadata.cpp | 5 +---- src/graphics/shader/shaderVertexMetadata.h | 11 +++++------ tests/ShaderVertexMetadataTests.cpp | 14 ++++++++------ 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/graphics/shader/shader.cpp b/src/graphics/shader/shader.cpp index 5df85b04a..d4ae88166 100644 --- a/src/graphics/shader/shader.cpp +++ b/src/graphics/shader/shader.cpp @@ -371,16 +371,15 @@ static void ShaderDetectBuffers(ShaderVertexInputInfo& info) { } static void ShaderApplyAttribSemantics(ShaderVertexInputInfo& info, - const ShaderSemantic* input_semantics, - uint32_t num_input_semantics, const uint32_t* attrib, - const uint32_t* buffer) { + std::span input_semantics, + const uint32_t* attrib, const uint32_t* buffer) { KYTY_PROFILER_FUNCTION(); EXIT_IF(attrib == nullptr || buffer == nullptr); const bool debug_dump = Config::GraphicsDebugDumpEnabled(); - for (uint32_t i = 0; i < num_input_semantics; i++) { + for (uint32_t i = 0; i < input_semantics.size(); i++) { const auto& in = input_semantics[i]; EXIT_NOT_IMPLEMENTED(in.static_vb_index == 1 || in.static_attribute == 1); @@ -534,8 +533,7 @@ static bool ShaderGetStaticVertexInputInfo(uint64_t shader_addr, const HW::UserS shader_addr); return false; } - ShaderApplyAttribSemantics(info, metadata.input_semantics.data(), - metadata.input_semantics_count, attrib, buffer); + ShaderApplyAttribSemantics(info, metadata.input_semantics, attrib, buffer); ShaderDetectBuffers(info); } return true; diff --git a/src/graphics/shader/shaderVertexMetadata.cpp b/src/graphics/shader/shaderVertexMetadata.cpp index ea06fc3ec..91544edcd 100644 --- a/src/graphics/shader/shaderVertexMetadata.cpp +++ b/src/graphics/shader/shaderVertexMetadata.cpp @@ -68,13 +68,10 @@ bool ShaderReadVertexMetadata(const ShaderMappedData& data, uint32_t max_user_sg return ShaderError::Fail(error, "vertex semantic count is outside the supported domain"); } - const auto semantic_size = - static_cast(data.num_input_semantics) * sizeof(ShaderSemantic); if (data.input_semantics == nullptr) { return ShaderError::Fail(error, "missing vertex input semantics"); } - std::memcpy(next.input_semantics.data(), data.input_semantics, semantic_size); - next.input_semantics_count = data.num_input_semantics; + next.input_semantics = {data.input_semantics, data.num_input_semantics}; metadata = next; return true; } diff --git a/src/graphics/shader/shaderVertexMetadata.h b/src/graphics/shader/shaderVertexMetadata.h index 5bb879459..95eb37922 100644 --- a/src/graphics/shader/shaderVertexMetadata.h +++ b/src/graphics/shader/shaderVertexMetadata.h @@ -3,19 +3,18 @@ #include "graphics/shader/shader.h" -#include +#include #include namespace Libs::Graphics { struct ShaderVertexMetadata { - int vertex_buffer_reg = -1; - int vertex_attrib_reg = -1; - std::array input_semantics {}; - uint32_t input_semantics_count = 0; + int vertex_buffer_reg = -1; + int vertex_attrib_reg = -1; + std::span input_semantics; }; -// Copies the small AGC metadata subset used by the vertex path after validating every guest range. +// Validates the vertex metadata and returns a view into the shader header. bool ShaderReadVertexMetadata(const ShaderMappedData& data, uint32_t max_user_sgprs, ShaderVertexMetadata& metadata, std::string* error); diff --git a/tests/ShaderVertexMetadataTests.cpp b/tests/ShaderVertexMetadataTests.cpp index 7d1078743..ed07b9c73 100644 --- a/tests/ShaderVertexMetadataTests.cpp +++ b/tests/ShaderVertexMetadataTests.cpp @@ -36,14 +36,16 @@ struct Fixture { 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::array prior_semantics {}; + output.vertex_buffer_reg = 37; + output.vertex_attrib_reg = 41; + output.input_semantics = prior_semantics; 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, + output.input_semantics.data() == prior_semantics.data() && + output.input_semantics.size() == prior_semantics.size(), "metadata rejection changed the prior output"); } @@ -54,7 +56,7 @@ void TestValidAndInvalidMetadata() { 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, + output.input_semantics.size() == 1, "valid AGC vertex metadata was decoded incorrectly"); Fixture buffer_only; @@ -65,7 +67,7 @@ void TestValidAndInvalidMetadata() { Check(ShaderReadVertexMetadata(buffer_only.mapped, 64, output, &error), "vertex-buffer-only AGC metadata was rejected"); Check(output.vertex_buffer_reg == 2 && output.vertex_attrib_reg == -1 && - output.input_semantics_count == 0, + output.input_semantics.empty(), "vertex-buffer-only AGC metadata was decoded incorrectly"); Fixture attrib_only;