#include "graphics/shader/shaderVertexMetadata.h" #include #include namespace Libs::Graphics { namespace { bool Fail(std::string* error, const char* message) { if (error != nullptr) { *error = message; } return false; } } // namespace bool ShaderReadVertexMetadata(const ShaderMappedData& data, uint32_t max_user_sgprs, ShaderVertexMetadata& metadata, std::string* error) { if (data.user_data == nullptr) { return Fail(error, "missing AGC user-data header"); } ShaderUserData user_data {}; std::memcpy(&user_data, data.user_data, sizeof(user_data)); constexpr uint32_t DirectResourceCount = static_cast(AgcDirectResourceType::Last) + 1u; if (user_data.direct_resource_count > DirectResourceCount) { return Fail(error, "AGC direct-resource count exceeds the known resource domain"); } std::array direct_offsets {}; const auto direct_size = static_cast(user_data.direct_resource_count) * sizeof(uint16_t); if (direct_size != 0) { if (user_data.direct_resource_offset == nullptr) { return Fail(error, "missing AGC direct-resource offsets"); } std::memcpy(direct_offsets.data(), user_data.direct_resource_offset, direct_size); } ShaderVertexMetadata next; for (uint32_t type = 0; type < user_data.direct_resource_count; type++) { const auto reg = direct_offsets[type]; if (reg == AGC_ILLEGAL_DIRECT_OFFSET) { continue; } switch (static_cast(type)) { case AgcDirectResourceType::PtrVertexBufferTable: next.vertex_buffer_reg = reg; break; case AgcDirectResourceType::PtrVertexAttribDescTable: next.vertex_attrib_reg = reg; break; default: break; } } const bool embedded = next.vertex_buffer_reg >= 0 || next.vertex_attrib_reg >= 0; if (!embedded) { metadata = next; return true; } if (next.vertex_buffer_reg < 0 || next.vertex_attrib_reg < 0) { return Fail(error, "vertex buffer and attribute tables must be supplied together"); } if (static_cast(next.vertex_buffer_reg) + 1u >= max_user_sgprs || static_cast(next.vertex_attrib_reg) + 1u >= max_user_sgprs) { return Fail(error, "vertex table pointer exceeds the user-SGPR domain"); } if (data.num_input_semantics == 0 || data.num_input_semantics > ShaderVertexInputInfo::RES_MAX) { return 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 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; metadata = next; return true; } } // namespace Libs::Graphics