Skip to content

Commit

Permalink
metal: improve shader resource binding code.
Browse files Browse the repository at this point in the history
  • Loading branch information
slime73 committed Jan 10, 2024
1 parent fb002ee commit 7ff6f74
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 42 deletions.
2 changes: 1 addition & 1 deletion src/modules/graphics/metal/Graphics.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ static bool isClampOne(SamplerState::WrapMode w)
if ((b.access & Shader::ACCESS_WRITE) != 0 && texture == nil)
allWritableVariablesSet = false;
}

if (sampindex != LOVE_UINT8_MAX)
setSampler(encoder, bindings, sampindex, samplertex);
}
Expand Down
102 changes: 61 additions & 41 deletions src/modules/graphics/metal/Shader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -390,20 +390,24 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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?
Expand All @@ -415,33 +419,6 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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;
Expand Down Expand Up @@ -571,7 +548,7 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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;
Expand Down Expand Up @@ -668,7 +645,11 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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++)
{
Expand All @@ -678,15 +659,8 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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;
Expand Down Expand Up @@ -726,7 +700,11 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)

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++)
{
Expand All @@ -752,6 +730,25 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
}
}

// 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];
}

Expand Down Expand Up @@ -878,6 +875,7 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
for (int i = 0; i < count; i++)
{
love::graphics::Texture *tex = textures[i];
bool isdefault = tex == nullptr;

if (tex != nullptr)
{
Expand All @@ -897,8 +895,17 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)

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;
}
}
}}

Expand All @@ -919,14 +926,24 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
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();

Expand All @@ -938,8 +955,11 @@ static EShLanguage getGLSLangStage(ShaderStageType stage)
}
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);
}
}
}
Expand Down

0 comments on commit 7ff6f74

Please sign in to comment.