mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
metal: fix structs in uniforms.
This commit is contained in:
@@ -39,6 +39,12 @@ namespace glslang
|
|||||||
class TProgram;
|
class TProgram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace spirv_cross
|
||||||
|
{
|
||||||
|
class CompilerMSL;
|
||||||
|
struct SPIRType;
|
||||||
|
}
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
{
|
{
|
||||||
namespace graphics
|
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);
|
void compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program);
|
||||||
|
|
||||||
id<MTLFunction> functions[SHADERSTAGE_MAX_ENUM];
|
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)
|
void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program)
|
||||||
{
|
{
|
||||||
using namespace glslang;
|
using namespace glslang;
|
||||||
@@ -513,8 +591,6 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
msl.add_msl_resource_binding(binding);
|
msl.add_msl_resource_binding(binding);
|
||||||
|
|
||||||
const SPIRType &type = msl.get_type(resource.base_type_id);
|
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);
|
size_t size = msl.get_declared_struct_size(type);
|
||||||
|
|
||||||
if (localUniformBufferSize != 0)
|
if (localUniformBufferSize != 0)
|
||||||
@@ -531,70 +607,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
memset(localUniformStagingData, 0, size);
|
memset(localUniformStagingData, 0, size);
|
||||||
memset(localUniformBufferData, 0, size);
|
memset(localUniformBufferData, 0, size);
|
||||||
|
|
||||||
for (size_t uindex = 0; uindex < membertypes.size(); uindex++)
|
std::string basename("");
|
||||||
{
|
buildLocalUniforms(msl, type, 0, basename);
|
||||||
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];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -233,7 +233,6 @@ void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, in
|
|||||||
options:MTLResourceStorageModeShared];
|
options:MTLResourceStorageModeShared];
|
||||||
|
|
||||||
MTLBlitOption options = MTLBlitOptionNone;
|
MTLBlitOption options = MTLBlitOptionNone;
|
||||||
|
|
||||||
if (isPixelFormatDepthStencil(format))
|
if (isPixelFormatDepthStencil(format))
|
||||||
options = MTLBlitOptionDepthFromDepthStencil;
|
options = MTLBlitOptionDepthFromDepthStencil;
|
||||||
|
|
||||||
@@ -272,7 +271,6 @@ void Texture::copyFromBuffer(love::graphics::Buffer *source, size_t sourceoffset
|
|||||||
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
||||||
|
|
||||||
MTLBlitOption options = MTLBlitOptionNone;
|
MTLBlitOption options = MTLBlitOptionNone;
|
||||||
|
|
||||||
if (isPixelFormatDepthStencil(format))
|
if (isPixelFormatDepthStencil(format))
|
||||||
options = MTLBlitOptionDepthFromDepthStencil;
|
options = MTLBlitOptionDepthFromDepthStencil;
|
||||||
|
|
||||||
@@ -302,7 +300,6 @@ void Texture::copyToBuffer(love::graphics::Buffer *dest, int slice, int mipmap,
|
|||||||
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
int z = texType == TEXTURE_VOLUME ? slice : 0;
|
||||||
|
|
||||||
MTLBlitOption options = MTLBlitOptionNone;
|
MTLBlitOption options = MTLBlitOptionNone;
|
||||||
|
|
||||||
if (isPixelFormatDepthStencil(format))
|
if (isPixelFormatDepthStencil(format))
|
||||||
options = MTLBlitOptionDepthFromDepthStencil;
|
options = MTLBlitOptionDepthFromDepthStencil;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user