mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
metal: improve shader resource binding code.
This commit is contained in:
@@ -1063,7 +1063,7 @@ bool Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
|||||||
if ((b.access & Shader::ACCESS_WRITE) != 0 && texture == nil)
|
if ((b.access & Shader::ACCESS_WRITE) != 0 && texture == nil)
|
||||||
allWritableVariablesSet = false;
|
allWritableVariablesSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sampindex != LOVE_UINT8_MAX)
|
if (sampindex != LOVE_UINT8_MAX)
|
||||||
setSampler(encoder, bindings, sampindex, samplertex);
|
setSampler(encoder, bindings, sampindex, samplertex);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -390,20 +390,24 @@ void Shader::addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Re
|
|||||||
case spv::Dim2D:
|
case spv::Dim2D:
|
||||||
u.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D;
|
u.textureType = basetype.image.arrayed ? TEXTURE_2D_ARRAY : TEXTURE_2D;
|
||||||
u.textures = new love::graphics::Texture*[u.count];
|
u.textures = new love::graphics::Texture*[u.count];
|
||||||
|
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
|
||||||
break;
|
break;
|
||||||
case spv::Dim3D:
|
case spv::Dim3D:
|
||||||
u.textureType = TEXTURE_VOLUME;
|
u.textureType = TEXTURE_VOLUME;
|
||||||
u.textures = new love::graphics::Texture*[u.count];
|
u.textures = new love::graphics::Texture*[u.count];
|
||||||
|
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
|
||||||
break;
|
break;
|
||||||
case spv::DimCube:
|
case spv::DimCube:
|
||||||
if (basetype.image.arrayed)
|
if (basetype.image.arrayed)
|
||||||
throw love::Exception("Cubemap Arrays are not currently supported.");
|
throw love::Exception("Cubemap Arrays are not currently supported.");
|
||||||
u.textureType = TEXTURE_CUBE;
|
u.textureType = TEXTURE_CUBE;
|
||||||
u.textures = new love::graphics::Texture*[u.count];
|
u.textures = new love::graphics::Texture*[u.count];
|
||||||
|
memset(u.textures, 0, sizeof(love::graphics::Texture *) * u.count);
|
||||||
break;
|
break;
|
||||||
case spv::DimBuffer:
|
case spv::DimBuffer:
|
||||||
u.baseType = UNIFORM_TEXELBUFFER;
|
u.baseType = UNIFORM_TEXELBUFFER;
|
||||||
u.buffers = new love::graphics::Buffer*[u.count];
|
u.buffers = new love::graphics::Buffer*[u.count];
|
||||||
|
memset(u.buffers, 0, sizeof(love::graphics::Buffer *) * u.count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// TODO: error? continue?
|
// 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++)
|
for (int i = 0; i < u.count; i++)
|
||||||
u.ints[i] = -1; // Initialized below, after compiling.
|
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;
|
uniforms[u.name] = u;
|
||||||
|
|
||||||
BuiltinUniform builtin;
|
BuiltinUniform builtin;
|
||||||
@@ -571,7 +548,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
{
|
{
|
||||||
u.ints[i] = -1; // Initialized below, after compiling.
|
u.ints[i] = -1; // Initialized below, after compiling.
|
||||||
u.buffers[i] = nullptr; // TODO
|
u.buffers[i] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uniforms[u.name] = u;
|
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);
|
uint32 samplerbinding = msl.get_automatic_msl_resource_binding_secondary(resource.id);
|
||||||
|
|
||||||
if (texturebinding == (uint32)-1)
|
if (texturebinding == (uint32)-1)
|
||||||
|
{
|
||||||
|
// No valid binding, the uniform was likely optimized out because it's not used.
|
||||||
|
uniforms.erase(resource.name);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
{
|
{
|
||||||
@@ -678,15 +659,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
TextureBinding b = {};
|
TextureBinding b = {};
|
||||||
b.access = u.access;
|
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;
|
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||||
if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
|
if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
|
||||||
b.isMainTexture = true;
|
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);
|
uint32 bufferbinding = msl.get_automatic_msl_resource_binding(resource.id);
|
||||||
if (bufferbinding == (uint32)-1)
|
if (bufferbinding == (uint32)-1)
|
||||||
|
{
|
||||||
|
// No valid binding, the uniform was likely optimized out because it's not used.
|
||||||
|
uniforms.erase(resource.name);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < u.count; i++)
|
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];
|
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++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
love::graphics::Texture *tex = textures[i];
|
love::graphics::Texture *tex = textures[i];
|
||||||
|
bool isdefault = tex == nullptr;
|
||||||
|
|
||||||
if (tex != nullptr)
|
if (tex != nullptr)
|
||||||
{
|
{
|
||||||
@@ -897,8 +895,17 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
|
|||||||
|
|
||||||
info->textures[i] = tex;
|
info->textures[i] = tex;
|
||||||
|
|
||||||
textureBindings[info->ints[i]].texture = getMTLTexture(tex);
|
auto &binding = textureBindings[info->ints[i]];
|
||||||
textureBindings[info->ints[i]].samplerTexture = tex;
|
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++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
love::graphics::Buffer *buffer = buffers[i];
|
love::graphics::Buffer *buffer = buffers[i];
|
||||||
|
bool isdefault = buffer == nullptr;
|
||||||
|
|
||||||
if (buffer != nullptr)
|
if (buffer != nullptr)
|
||||||
{
|
{
|
||||||
if (!validateBuffer(info, buffer, false))
|
if (!validateBuffer(info, buffer, false))
|
||||||
continue;
|
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)
|
if (info->buffers[i] != nullptr)
|
||||||
info->buffers[i]->release();
|
info->buffers[i]->release();
|
||||||
@@ -938,8 +955,11 @@ void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffe
|
|||||||
}
|
}
|
||||||
else if (storagebinding)
|
else if (storagebinding)
|
||||||
{
|
{
|
||||||
// TODO
|
auto &binding = bufferBindings[info->ints[i]];
|
||||||
bufferBindings[info->ints[i]].buffer = getMTLBuffer(buffer);
|
if (isdefault && (binding.access & ACCESS_WRITE) != 0)
|
||||||
|
binding.buffer = nil;
|
||||||
|
else
|
||||||
|
binding.buffer = getMTLBuffer(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user