[Feat] (MG_Util/ShaderCompiler): extract global UBO offset from GL plain uniforms

This commit is contained in:
2025-08-08 13:46:08 +08:00
parent fcd52a9177
commit 916fdf40af
5 changed files with 81 additions and 22 deletions
+17 -2
View File
@@ -287,6 +287,21 @@ TEST_F(ProgramTest, DecompProgram) {
}
}
auto ubo0 = sessions[0].GetShaderInterface(SPVC_RESOURCE_TYPE_UNIFORM_BUFFER);
auto ubo1 = sessions[1].GetShaderInterface(SPVC_RESOURCE_TYPE_UNIFORM_BUFFER);
auto& meta0 = sessions[0].GetMetadata();
auto& meta1 = sessions[1].GetMetadata();
for (auto& [name, offset] : meta0.plainUniformOffsetsInUBO) {
printf("%s: \t%u\n", name.c_str(), offset);
}
printf("\n");
for (auto& [name, offset] : meta1.plainUniformOffsetsInUBO) {
printf("%s: \t%u\n", name.c_str(), offset);
}
EXPECT_EQ(meta0.plainUniformOffsetsInUBO.size(), meta1.plainUniformOffsetsInUBO.size());
for (auto& [name, offset] : meta0.plainUniformOffsetsInUBO) {
EXPECT_EQ(offset, meta1.plainUniformOffsetsInUBO.at(name));
}
}
@@ -137,7 +137,7 @@ namespace MobileGL {
tshader->setAutoMapLocations(true);
tshader->setAutoMapBindings(true);
tshader->setEnvInputVulkanRulesRelaxed(); // using EXT_vulkan_glsl_relaxed for gl_VertexID and gl_InstanceID?
tshader->setGlobalUniformBlockName("MGL_GLOBAL_UBO");
tshader->setGlobalUniformBlockName(GLOBAL_UBO_NAME);
if (!tshader->parse(&GetTBuiltInResourceInstance(), 150, ECoreProfile,
/*forceDefaultVersionAndProfile: */false,
/*forwardCompatible: */true, EShMsgDefault)) {
@@ -54,32 +54,52 @@ namespace ShaderTranspiler {
var.name = list[i].name;
var.location = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationLocation);
variables.push_back(var);
if (resource_type == SPVC_RESOURCE_TYPE_UNIFORM_BUFFER) {
spvc_type type = spvc_compiler_get_type_handle(compiler, list[i].base_type_id);
size_t num_members = spvc_type_get_num_member_types(type);
printf("uniform %s {\n", var.name.c_str());
for (size_t j = 0; j < num_members; ++j) {
const char *memberName = spvc_compiler_get_member_name(compiler, list[i].base_type_id, j);
// auto memberTypeId = spvc_type_get_member_type(type, j);
// auto memberType = spvc_compiler_get_type_handle(compiler, memberTypeId);
unsigned memberOffset = 0;
spvc_compiler_type_struct_member_offset(compiler, type, j, &memberOffset);
printf("\b%s; // %u\n", memberName, memberOffset);
}
printf("}\n");
}
}
std::sort(variables.begin(), variables.end());
return variables;
}
spvc_result SpvcSession::Compile(const char** result) const {
return spvc_compiler_compile(compiler, result);
spvc_result SpvcSession::Compile(const char** result) {
SPVC_CHK_INIT
SPVC_CHK_RESULT(spvc_compiler_compile(compiler, result));
SPVC_CHK_RESULT(ParseMetaData());
SPVC_CHK_RETURN
}
spvc_result SpvcSession::ParseMetaData() {
SPVC_CHK_INIT
metadata = SpvcMetadata();
const spvc_reflected_resource *list = nullptr;
size_t count = 0;
SPVC_CHK_RESULT(
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
)
for (size_t i = 0; i < count; ++i) {
if (spvc_compiler_has_decoration(compiler, list[i].id, SpvDecorationBuiltIn)) {
continue;
}
if (strcmp(list[i].name, GLOBAL_UBO_NAME) == 0) {
spvc_type type = spvc_compiler_get_type_handle(compiler, list[i].base_type_id);
size_t num_members = spvc_type_get_num_member_types(type);
for (size_t j = 0; j < num_members; ++j) {
const char *memberName = spvc_compiler_get_member_name(compiler, list[i].base_type_id, j);
unsigned memberOffset = 0;
SPVC_CHK_RESULT(spvc_compiler_type_struct_member_offset(compiler, type, j, &memberOffset);)
metadata.plainUniformOffsetsInUBO[memberName] = memberOffset;
}
}
}
SPVC_CHK_RETURN
}
const SpvcMetadata& SpvcSession::GetMetadata() const {
return metadata;
}
const char* SpvcSession::GetLastErrorString() const {
return spvc_context_get_last_error_string(context);
@@ -7,9 +7,25 @@
#pragma once
#define SPVC_CHK_INIT \
auto __r = SPVC_SUCCESS;
#define SPVC_CHK_RESULT(res) \
__r = res; \
if (__r != SPVC_SUCCESS) { \
return __r; \
}
#define SPVC_CHK_RETURN \
return __r;
namespace MobileGL {
namespace MG_Util {
namespace ShaderTranspiler {
struct SpvcMetadata {
UnorderedMap<String, unsigned> plainUniformOffsetsInUBO;
};
class SpvcSession {
public:
SpvcSession() {}
@@ -29,15 +45,21 @@ namespace ShaderTranspiler {
spvc_result CreateOptions(spvc_compiler_options *options);
spvc_result SetOptions(spvc_compiler_options options);
Vector<InterfaceVariable> GetShaderInterface(spvc_resource_type resource_type) const;
spvc_result Compile(const char** result) const;
spvc_result Compile(const char** result);
const SpvcMetadata& GetMetadata() const;
const char* GetLastErrorString() const;
private:
// Should be called once, and only once, for every SPIR-V binary
spvc_result ParseMetaData();
spvc_context context = nullptr;
spvc_parsed_ir ir = nullptr;
spvc_compiler compiler = nullptr;
spvc_compiler_options compiler_options = nullptr;
spvc_resources resources = nullptr;
SpvcMetadata metadata;
};
}
}
@@ -4,6 +4,8 @@
namespace MobileGL {
namespace MG_Util {
namespace ShaderTranspiler {
inline const char* GLOBAL_UBO_NAME = "MGL_GLOBAL_UBO";
struct EmptyType {};
struct ShaderAttrib {