mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
metal: support constant initializer values for local uniforms.
This commit is contained in:
@@ -792,6 +792,24 @@ static PixelFormat getPixelFormat(glslang::TLayoutFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T convertData(const glslang::TConstUnion &data)
|
||||
{
|
||||
switch (data.getType())
|
||||
{
|
||||
case glslang::EbtInt: return (T) data.getIConst();
|
||||
case glslang::EbtUint: return (T) data.getUConst();
|
||||
case glslang::EbtDouble: return (T) data.getDConst();
|
||||
case glslang::EbtInt8: return (T) data.getI8Const();
|
||||
case glslang::EbtInt16: return (T) data.getI16Const();
|
||||
case glslang::EbtInt64: return (T) data.getI64Const();
|
||||
case glslang::EbtUint8: return (T) data.getU8Const();
|
||||
case glslang::EbtUint16: return (T) data.getU16Const();
|
||||
case glslang::EbtUint64: return (T) data.getU64Const();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err, ValidationReflection &reflection)
|
||||
{
|
||||
glslang::TProgram program;
|
||||
@@ -871,6 +889,50 @@ bool Shader::validateInternal(StrongRef<ShaderStage> stages[], std::string &err,
|
||||
|
||||
reflection.storageTextures[info.name] = texreflection;
|
||||
}
|
||||
else if (!type->isOpaque())
|
||||
{
|
||||
LocalUniform u = {};
|
||||
auto &values = u.initializerValues;
|
||||
const glslang::TConstUnionArray *constarray = info.getConstArray();
|
||||
|
||||
// Store initializer values for local uniforms. Some love graphics
|
||||
// backends strip these out of the shader so we need to be able to
|
||||
// access them (to re-send them) by getting them here.
|
||||
switch (type->getBasicType())
|
||||
{
|
||||
case glslang::EbtFloat:
|
||||
u.dataType = DATA_BASETYPE_FLOAT;
|
||||
if (constarray != nullptr)
|
||||
{
|
||||
values.resize(constarray->size());
|
||||
for (int i = 0; i < constarray->size(); i++)
|
||||
values[i].f = convertData<float>((*constarray)[i]);
|
||||
}
|
||||
break;
|
||||
case glslang::EbtUint:
|
||||
u.dataType = DATA_BASETYPE_UINT;
|
||||
if (constarray != nullptr)
|
||||
{
|
||||
values.resize(constarray->size());
|
||||
for (int i = 0; i < constarray->size(); i++)
|
||||
values[i].u = convertData<uint32>((*constarray)[i]);
|
||||
}
|
||||
break;
|
||||
case glslang::EbtInt:
|
||||
case glslang::EbtBool:
|
||||
default:
|
||||
u.dataType = DATA_BASETYPE_INT;
|
||||
if (constarray != nullptr)
|
||||
{
|
||||
values.resize(constarray->size());
|
||||
for (int i = 0; i < constarray->size(); i++)
|
||||
values[i].i = convertData<int32>((*constarray)[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
reflection.localUniforms[info.name] = u;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < program.getNumBufferBlocks(); i++)
|
||||
|
||||
@@ -158,6 +158,13 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
union LocalUniformValue
|
||||
{
|
||||
float f;
|
||||
int32 i;
|
||||
uint32 u;
|
||||
};
|
||||
|
||||
// The members in here must respect uniform buffer alignment/padding rules.
|
||||
struct BuiltinUniformData
|
||||
{
|
||||
@@ -259,10 +266,17 @@ protected:
|
||||
Access access;
|
||||
};
|
||||
|
||||
struct LocalUniform
|
||||
{
|
||||
DataBaseType dataType;
|
||||
std::vector<LocalUniformValue> initializerValues;
|
||||
};
|
||||
|
||||
struct ValidationReflection
|
||||
{
|
||||
std::map<std::string, BufferReflection> storageBuffers;
|
||||
std::map<std::string, StorageTextureReflection> storageTextures;
|
||||
std::map<std::string, LocalUniform> localUniforms;
|
||||
int localThreadgroupSize[3];
|
||||
bool usesPointSize;
|
||||
};
|
||||
|
||||
@@ -565,6 +565,16 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
u.matrix.rows = membertype.vecsize;
|
||||
u.matrix.columns = membertype.columns;
|
||||
}
|
||||
if (validationReflection.localUniforms.find(u.name) != validationReflection.localUniforms.end())
|
||||
{
|
||||
const auto &ru = validationReflection.localUniforms.find(u.name);
|
||||
const auto &values = ru->second.initializerValues;
|
||||
if (!values.empty())
|
||||
{
|
||||
memcpy(u.data, values.data(), std::min(u.dataSize, values.size() * sizeof(LocalUniformValue)));
|
||||
}
|
||||
}
|
||||
updateUniform(&u, u.count);
|
||||
break;
|
||||
case SPIRType::Struct:
|
||||
// TODO
|
||||
@@ -582,6 +592,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
builtinUniformDataOffset = offset;
|
||||
builtinUniformInfo[builtin] = &uniforms[u.name];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user