metal: improve shader resource binding code.

This commit is contained in:
Sasha Szpakowski
2024-01-09 21:11:04 -04:00
parent fb002ee59b
commit 7ff6f74a92
2 changed files with 62 additions and 42 deletions
+1 -1
View File
@@ -1063,7 +1063,7 @@ bool Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
if ((b.access & Shader::ACCESS_WRITE) != 0 && texture == nil)
allWritableVariablesSet = false;
}
if (sampindex != LOVE_UINT8_MAX)
setSampler(encoder, bindings, sampindex, samplertex);
}
+61 -41
View File
@@ -390,20 +390,24 @@ void Shader::addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Re
case spv::Dim2D:
u.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D;
u.textures = new love::graphics::Texture*[u.count];
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
break;
case spv::Dim3D:
u.textureType = TEXTURE_VOLUME;
u.textures = new love::graphics::Texture*[u.count];
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
break;
case spv::DimCube:
if (basetype.image.arrayed)
throw love::Exception("Cubemap Arrays are not currently supported.");
u.textureType = TEXTURE_CUBE;
u.textures = new love::graphics::Texture*[u.count];
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
break;
case spv::DimBuffer:
u.baseType = UNIFORM_TEXELBUFFER;
u.buffers = new love::graphics::Buffer*[u.count];
memset(u.buffers, 0, sizeof(love::graphics::Buffer *) * u.count);
break;
default:
// TODO: error? continue?
@@ -415,33 +419,6 @@ void Shader::addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Re
for (int i = 0; i < u.count; i++)
u.ints[i] = -1; // Initialized below, after compiling.
if (u.baseType == UNIFORM_SAMPLER)
{
auto tex = Graphics::getInstance()->getDefaultTexture(u.textureType, u.dataBaseType);
for (int i = 0; i < u.count; i++)
{
tex->retain();
u.textures[i] = tex;
}
}
else if (u.baseType == UNIFORM_TEXELBUFFER)
{
for (int i = 0; i < u.count; i++)
u.buffers[i] = nullptr; // TODO
}
else if (u.baseType == UNIFORM_STORAGETEXTURE)
{
Texture *tex = nullptr;
if ((u.access & ACCESS_WRITE) == 0)
tex = Graphics::getInstance()->getDefaultTexture(u.textureType, u.dataBaseType);
for (int i = 0; i < u.count; i++)
{
if (tex)
tex->retain();
u.textures[i] = tex;
}
}
uniforms[u.name] = u;
BuiltinUniform builtin;
@@ -571,7 +548,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
for (int i = 0; i < u.count; i++)
{
u.ints[i] = -1; // Initialized below, after compiling.
u.buffers[i] = nullptr; // TODO
u.buffers[i] = nullptr;
}
uniforms[u.name] = u;
@@ -668,7 +645,11 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
uint32 samplerbinding = msl.get_automatic_msl_resource_binding_secondary(resource.id);
if (texturebinding == (uint32)-1)
{
// No valid binding, the uniform was likely optimized out because it's not used.
uniforms.erase(resource.name);
return;
}
for (int i = 0; i < u.count; i++)
{
@@ -678,15 +659,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
TextureBinding b = {};
b.access = u.access;
if (u.baseType == UNIFORM_TEXELBUFFER)
if (u.baseType == UNIFORM_SAMPLER)
{
// TODO
}
else
{
b.texture = getMTLTexture(u.textures[i]);
b.samplerTexture = u.textures[i];
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
b.isMainTexture = true;
@@ -726,7 +700,11 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
uint32 bufferbinding = msl.get_automatic_msl_resource_binding(resource.id);
if (bufferbinding == (uint32)-1)
{
// No valid binding, the uniform was likely optimized out because it's not used.
uniforms.erase(resource.name);
continue;
}
for (int i = 0; i < u.count; i++)
{
@@ -752,6 +730,25 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
}
}
// Initialize default resource bindings.
for (auto &kvp : uniforms)
{
UniformInfo &info = kvp.second;
switch (info.baseType)
{
case UNIFORM_SAMPLER:
case UNIFORM_STORAGETEXTURE:
sendTextures(&info, info.textures, info.count);
break;
case UNIFORM_TEXELBUFFER:
case UNIFORM_STORAGEBUFFER:
sendBuffers(&info, info.buffers, info.count);
break;
default:
break;
}
}
firstVertexBufferBinding = metalBufferIndices[SHADERSTAGE_VERTEX];
}
@@ -878,6 +875,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
for (int i = 0; i < count; i++)
{
love::graphics::Texture *tex = textures[i];
bool isdefault = tex == nullptr;
if (tex != nullptr)
{
@@ -897,8 +895,17 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
info->textures[i] = tex;
textureBindings[info->ints[i]].texture = getMTLTexture(tex);
textureBindings[info->ints[i]].samplerTexture = tex;
auto &binding = textureBindings[info->ints[i]];
if (isdefault && (binding.access & ACCESS_WRITE) != 0)
{
binding.texture = nil;
binding.samplerTexture = nullptr;
}
else
{
binding.texture = getMTLTexture(tex);
binding.samplerTexture = tex;
}
}
}}
@@ -919,13 +926,23 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
for (int i = 0; i < count; i++)
{
love::graphics::Buffer *buffer = buffers[i];
bool isdefault = buffer == nullptr;
if (buffer != nullptr)
{
if (!validateBuffer(info, buffer, false))
continue;
buffer->retain();
}
else
{
auto gfx = Graphics::getInstance();
if (texelbinding)
buffer = gfx->getDefaultTexelBuffer(info->dataBaseType);
else
buffer = gfx->getDefaultStorageBuffer();
}
buffer->retain();
if (info->buffers[i] != nullptr)
info->buffers[i]->release();
@@ -938,8 +955,11 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
}
else if (storagebinding)
{
// TODO
bufferBindings[info->ints[i]].buffer = getMTLBuffer(buffer);
auto &binding = bufferBindings[info->ints[i]];
if (isdefault && (binding.access & ACCESS_WRITE) != 0)
binding.buffer = nil;
else
binding.buffer = getMTLBuffer(buffer);
}
}
}