feat: add unity-aligned shader contract metadata
This commit is contained in:
@@ -431,6 +431,62 @@ bool TryParseShaderBackend(const Containers::String& value, ShaderBackend& outBa
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryParseShaderPropertyType(const Containers::String& value, ShaderPropertyType& outType) {
|
||||
const Containers::String normalized = value.Trim().ToLower();
|
||||
if (normalized == "float") {
|
||||
outType = ShaderPropertyType::Float;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "range") {
|
||||
outType = ShaderPropertyType::Range;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "int" || normalized == "integer") {
|
||||
outType = ShaderPropertyType::Int;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "vector" || normalized == "float4") {
|
||||
outType = ShaderPropertyType::Vector;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "color") {
|
||||
outType = ShaderPropertyType::Color;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "2d" || normalized == "texture2d" || normalized == "texture") {
|
||||
outType = ShaderPropertyType::Texture2D;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "cube" || normalized == "cubemap" || normalized == "texturecube") {
|
||||
outType = ShaderPropertyType::TextureCube;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TryParseShaderResourceType(const Containers::String& value, ShaderResourceType& outType) {
|
||||
const Containers::String normalized = value.Trim().ToLower();
|
||||
if (normalized == "constantbuffer" || normalized == "cbuffer" || normalized == "cbv") {
|
||||
outType = ShaderResourceType::ConstantBuffer;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "texture2d" || normalized == "texture" || normalized == "srvtexture2d") {
|
||||
outType = ShaderResourceType::Texture2D;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "texturecube" || normalized == "cubemap") {
|
||||
outType = ShaderResourceType::TextureCube;
|
||||
return true;
|
||||
}
|
||||
if (normalized == "sampler" || normalized == "samplerstate") {
|
||||
outType = ShaderResourceType::Sampler;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Containers::String GetDefaultEntryPoint(ShaderLanguage language, ShaderType stage) {
|
||||
if (language != ShaderLanguage::HLSL) {
|
||||
return Containers::String("main");
|
||||
@@ -520,14 +576,47 @@ bool ReadTextFile(const Containers::String& path, Containers::String& outText) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryParseUnsignedValue(const std::string& json, const char* key, Core::uint32& outValue) {
|
||||
size_t valuePos = 0;
|
||||
if (!FindValueStart(json, key, valuePos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t endPos = valuePos;
|
||||
while (endPos < json.size() && std::isdigit(static_cast<unsigned char>(json[endPos])) != 0) {
|
||||
++endPos;
|
||||
}
|
||||
|
||||
if (endPos == valuePos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
outValue = static_cast<Core::uint32>(std::stoul(json.substr(valuePos, endPos - valuePos)));
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t CalculateShaderMemorySize(const Shader& shader) {
|
||||
size_t memorySize = sizeof(Shader) + shader.GetName().Length() + shader.GetPath().Length();
|
||||
for (const ShaderPropertyDesc& property : shader.GetProperties()) {
|
||||
memorySize += property.name.Length();
|
||||
memorySize += property.displayName.Length();
|
||||
memorySize += property.defaultValue.Length();
|
||||
memorySize += property.semantic.Length();
|
||||
}
|
||||
for (const ShaderPass& pass : shader.GetPasses()) {
|
||||
memorySize += pass.name.Length();
|
||||
for (const ShaderPassTagEntry& tag : pass.tags) {
|
||||
memorySize += tag.name.Length();
|
||||
memorySize += tag.value.Length();
|
||||
}
|
||||
for (const ShaderResourceBindingDesc& binding : pass.resources) {
|
||||
memorySize += binding.name.Length();
|
||||
memorySize += binding.semantic.Length();
|
||||
}
|
||||
for (const ShaderStageVariant& variant : pass.variants) {
|
||||
memorySize += variant.entryPoint.Length();
|
||||
memorySize += variant.profile.Length();
|
||||
@@ -583,6 +672,38 @@ LoadResult LoadShaderManifest(const Containers::String& path, const std::string&
|
||||
|
||||
shader->Initialize(params);
|
||||
|
||||
std::string propertiesArray;
|
||||
if (TryExtractArray(jsonText, "properties", propertiesArray)) {
|
||||
std::vector<std::string> propertyObjects;
|
||||
if (!SplitTopLevelArrayElements(propertiesArray, propertyObjects)) {
|
||||
return LoadResult("Shader manifest properties array could not be parsed: " + path);
|
||||
}
|
||||
|
||||
for (const std::string& propertyObject : propertyObjects) {
|
||||
ShaderPropertyDesc property = {};
|
||||
if (!TryParseStringValue(propertyObject, "name", property.name) || property.name.Empty()) {
|
||||
return LoadResult("Shader manifest property is missing a valid name: " + path);
|
||||
}
|
||||
|
||||
Containers::String propertyTypeName;
|
||||
if (!TryParseStringValue(propertyObject, "type", propertyTypeName) ||
|
||||
!TryParseShaderPropertyType(propertyTypeName, property.type)) {
|
||||
return LoadResult("Shader manifest property has an invalid type: " + path);
|
||||
}
|
||||
|
||||
if (!TryParseStringValue(propertyObject, "displayName", property.displayName)) {
|
||||
property.displayName = property.name;
|
||||
}
|
||||
|
||||
if (!TryParseStringValue(propertyObject, "defaultValue", property.defaultValue)) {
|
||||
TryParseStringValue(propertyObject, "default", property.defaultValue);
|
||||
}
|
||||
|
||||
TryParseStringValue(propertyObject, "semantic", property.semantic);
|
||||
shader->AddProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& passObject : passObjects) {
|
||||
Containers::String passName;
|
||||
if (!TryParseStringValue(passObject, "name", passName) || passName.Empty()) {
|
||||
@@ -600,6 +721,38 @@ LoadResult LoadShaderManifest(const Containers::String& path, const std::string&
|
||||
}
|
||||
}
|
||||
|
||||
std::string resourcesArray;
|
||||
if (TryExtractArray(passObject, "resources", resourcesArray)) {
|
||||
std::vector<std::string> resourceObjects;
|
||||
if (!SplitTopLevelArrayElements(resourcesArray, resourceObjects)) {
|
||||
return LoadResult("Shader manifest pass resources could not be parsed: " + path);
|
||||
}
|
||||
|
||||
for (const std::string& resourceObject : resourceObjects) {
|
||||
ShaderResourceBindingDesc resourceBinding = {};
|
||||
if (!TryParseStringValue(resourceObject, "name", resourceBinding.name) ||
|
||||
resourceBinding.name.Empty()) {
|
||||
return LoadResult("Shader manifest pass resource is missing a valid name: " + path);
|
||||
}
|
||||
|
||||
Containers::String resourceTypeName;
|
||||
if (!TryParseStringValue(resourceObject, "type", resourceTypeName) ||
|
||||
!TryParseShaderResourceType(resourceTypeName, resourceBinding.type)) {
|
||||
return LoadResult("Shader manifest pass resource has an invalid type: " + path);
|
||||
}
|
||||
|
||||
if (!TryParseUnsignedValue(resourceObject, "set", resourceBinding.set)) {
|
||||
return LoadResult("Shader manifest pass resource is missing a valid set: " + path);
|
||||
}
|
||||
if (!TryParseUnsignedValue(resourceObject, "binding", resourceBinding.binding)) {
|
||||
return LoadResult("Shader manifest pass resource is missing a valid binding: " + path);
|
||||
}
|
||||
|
||||
TryParseStringValue(resourceObject, "semantic", resourceBinding.semantic);
|
||||
shader->AddPassResourceBinding(passName, resourceBinding);
|
||||
}
|
||||
}
|
||||
|
||||
std::string variantsArray;
|
||||
if (!TryExtractArray(passObject, "variants", variantsArray)) {
|
||||
return LoadResult("Shader manifest pass is missing variants: " + path);
|
||||
|
||||
Reference in New Issue
Block a user