mirror of
https://github.com/love2d/love.git
synced 2026-08-15 07:41:11 +02:00
metal: fix structs in uniforms.
This commit is contained in:
@@ -39,6 +39,12 @@ namespace glslang
|
||||
class TProgram;
|
||||
}
|
||||
|
||||
namespace spirv_cross
|
||||
{
|
||||
class CompilerMSL;
|
||||
struct SPIRType;
|
||||
}
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
@@ -128,6 +134,7 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
void buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename);
|
||||
void compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program);
|
||||
|
||||
id<MTLFunction> functions[SHADERSTAGE_MAX_ENUM];
|
||||
|
||||
@@ -376,6 +376,84 @@ Shader::Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stag
|
||||
}
|
||||
}}
|
||||
|
||||
void Shader::buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename)
|
||||
{
|
||||
using namespace spirv_cross;
|
||||
|
||||
const auto &membertypes = type.member_types;
|
||||
|
||||
for (size_t uindex = 0; uindex < membertypes.size(); uindex++)
|
||||
{
|
||||
const auto &membertype = msl.get_type(membertypes[uindex]);
|
||||
size_t membersize = msl.get_declared_struct_member_size(type, uindex);
|
||||
size_t offset = baseoffset + msl.type_struct_member_offset(type, uindex);
|
||||
|
||||
std::string name = basename + msl.get_member_name(type.self, uindex);
|
||||
|
||||
switch (membertype.basetype)
|
||||
{
|
||||
case SPIRType::Struct:
|
||||
name += ".";
|
||||
buildLocalUniforms(msl, membertype, offset, name);
|
||||
continue;
|
||||
case SPIRType::Int:
|
||||
case SPIRType::UInt:
|
||||
case SPIRType::Float:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (offset + membersize > localUniformBufferSize)
|
||||
throw love::Exception("Invalid uniform offset + size for '%s' (offset=%d, size=%d, buffer size=%d)", name.c_str(), (int)offset, (int)membersize, (int)localUniformBufferSize);
|
||||
|
||||
UniformInfo u = {};
|
||||
u.name = name;
|
||||
u.dataSize = membersize;
|
||||
u.count = membertype.array.empty() ? 1 : membertype.array[0];
|
||||
u.components = 1;
|
||||
|
||||
u.data = localUniformStagingData + offset;
|
||||
if (membertype.columns == 1)
|
||||
{
|
||||
if (membertype.basetype == SPIRType::Int)
|
||||
u.baseType = UNIFORM_INT;
|
||||
else if (membertype.basetype == SPIRType::UInt)
|
||||
u.baseType = UNIFORM_UINT;
|
||||
else
|
||||
u.baseType = UNIFORM_FLOAT;
|
||||
u.components = membertype.vecsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
u.baseType = UNIFORM_MATRIX;
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
uniforms[u.name] = u;
|
||||
|
||||
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||
if (getConstant(u.name.c_str(), builtin))
|
||||
{
|
||||
if (builtin == BUILTIN_UNIFORMS_PER_DRAW)
|
||||
builtinUniformDataOffset = offset;
|
||||
builtinUniformInfo[builtin] = &uniforms[u.name];
|
||||
}
|
||||
|
||||
updateUniform(&u, u.count);
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program)
|
||||
{
|
||||
using namespace glslang;
|
||||
@@ -513,8 +591,6 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
msl.add_msl_resource_binding(binding);
|
||||
|
||||
const SPIRType &type = msl.get_type(resource.base_type_id);
|
||||
const auto &membertypes = type.member_types;
|
||||
|
||||
size_t size = msl.get_declared_struct_size(type);
|
||||
|
||||
if (localUniformBufferSize != 0)
|
||||
@@ -531,70 +607,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
memset(localUniformStagingData, 0, size);
|
||||
memset(localUniformBufferData, 0, size);
|
||||
|
||||
for (size_t uindex = 0; uindex < membertypes.size(); uindex++)
|
||||
{
|
||||
const auto &membertype = msl.get_type(membertypes[uindex]);
|
||||
size_t membersize = msl.get_declared_struct_member_size(type, uindex);
|
||||
size_t offset = msl.type_struct_member_offset(type, uindex);
|
||||
|
||||
UniformInfo u = {};
|
||||
u.name = msl.get_member_name(type.self, uindex);
|
||||
u.dataSize = membersize;
|
||||
u.count = membertype.array.empty() ? 1 : membertype.array[0];
|
||||
u.components = 1;
|
||||
|
||||
switch (membertype.basetype)
|
||||
{
|
||||
case SPIRType::Int:
|
||||
case SPIRType::UInt:
|
||||
case SPIRType::Float:
|
||||
u.data = localUniformStagingData + offset;
|
||||
if (membertype.columns == 1)
|
||||
{
|
||||
if (membertype.basetype == SPIRType::Int)
|
||||
u.baseType = UNIFORM_INT;
|
||||
else if (membertype.basetype == SPIRType::UInt)
|
||||
u.baseType = UNIFORM_UINT;
|
||||
else
|
||||
u.baseType = UNIFORM_FLOAT;
|
||||
u.components = membertype.vecsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
u.baseType = UNIFORM_MATRIX;
|
||||
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
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uniforms[u.name] = u;
|
||||
|
||||
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||
if (getConstant(u.name.c_str(), builtin))
|
||||
{
|
||||
if (builtin == BUILTIN_UNIFORMS_PER_DRAW)
|
||||
builtinUniformDataOffset = offset;
|
||||
builtinUniformInfo[builtin] = &uniforms[u.name];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
std::string basename("");
|
||||
buildLocalUniforms(msl, type, 0, basename);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -233,7 +233,6 @@ void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, in
|
||||
options:MTLResourceStorageModeShared];
|
||||
|
||||
MTLBlitOption options = MTLBlitOptionNone;
|
||||
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
options = MTLBlitOptionDepthFromDepthStencil;
|
||||
|
||||
@@ -272,7 +271,6 @@ void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset
|
||||
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
||||
|
||||
MTLBlitOption options = MTLBlitOptionNone;
|
||||
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
options = MTLBlitOptionDepthFromDepthStencil;
|
||||
|
||||
@@ -302,7 +300,6 @@ void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap,
|
||||
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
||||
|
||||
MTLBlitOption options = MTLBlitOptionNone;
|
||||
|
||||
if (isPixelFormatDepthStencil(format))
|
||||
options = MTLBlitOptionDepthFromDepthStencil;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user