mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
metal: initial texel buffer Shader:send implementation
This commit is contained in:
@@ -762,7 +762,7 @@ bool Shader::validateTexture(const UniformInfo *info, Texture *tex, bool interna
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isTexelBufferTypeCompatible(DataBaseType a, DataBaseType b)
|
||||
static bool isTexelBaseTypeCompatible(DataBaseType a, DataBaseType b)
|
||||
{
|
||||
if (a == DATA_BASETYPE_FLOAT || a == DATA_BASETYPE_UNORM || a == DATA_BASETYPE_SNORM)
|
||||
return b == DATA_BASETYPE_FLOAT || b == DATA_BASETYPE_UNORM || b == DATA_BASETYPE_SNORM;
|
||||
@@ -803,7 +803,7 @@ bool Shader::validateBuffer(const UniformInfo *info, Buffer *buffer, bool intern
|
||||
if (texelbinding)
|
||||
{
|
||||
DataBaseType basetype = buffer->getDataMember(0).info.baseType;
|
||||
if (!isTexelBufferTypeCompatible(basetype, info->texelBufferType))
|
||||
if (!isTexelBaseTypeCompatible(basetype, info->dataBaseType))
|
||||
{
|
||||
if (internalUpdate)
|
||||
return false;
|
||||
|
||||
@@ -124,8 +124,8 @@ public:
|
||||
};
|
||||
|
||||
UniformType baseType;
|
||||
DataBaseType dataBaseType;
|
||||
TextureType textureType;
|
||||
DataBaseType texelBufferType;
|
||||
bool isDepthSampler;
|
||||
size_t bufferStride;
|
||||
size_t bufferMemberCount;
|
||||
|
||||
@@ -77,7 +77,7 @@ Buffer::Buffer(love::graphics::Graphics *gfx, id<MTLDevice> device, const Settin
|
||||
{
|
||||
MTLPixelFormat pixformat = getMTLPixelFormat(getDataMember(0).decl.format);
|
||||
auto desc = [MTLTextureDescriptor textureBufferDescriptorWithPixelFormat:pixformat
|
||||
width:size
|
||||
width:arraylength
|
||||
resourceOptions:opts
|
||||
usage:MTLTextureUsageShaderRead];
|
||||
texture = [buffer newTextureWithDescriptor:desc offset:0 bytesPerRow:size];
|
||||
|
||||
@@ -84,6 +84,12 @@ public:
|
||||
uint8 samplerstages[ShaderStage::STAGE_MAX_ENUM];
|
||||
};
|
||||
|
||||
struct BufferBinding
|
||||
{
|
||||
id<MTLBuffer> buffer;
|
||||
uint8 stages[ShaderStage::STAGE_MAX_ENUM];
|
||||
};
|
||||
|
||||
Shader(id<MTLDevice> device, love::graphics::ShaderStage *vertex, love::graphics::ShaderStage *pixel);
|
||||
virtual ~Shader();
|
||||
|
||||
@@ -104,6 +110,7 @@ public:
|
||||
|
||||
static int getUniformBufferBinding();
|
||||
const std::vector<TextureBinding> &getTextureBindings() const { return textureBindings; }
|
||||
const std::vector<BufferBinding> &getBufferBindings() const { return bufferBindings; }
|
||||
|
||||
uint8 *getLocalUniformBufferData() { return localUniformBufferData; }
|
||||
size_t getLocalUniformBufferSize() const { return localUniformBufferSize; }
|
||||
@@ -133,6 +140,7 @@ private:
|
||||
std::map<std::string, int> attributes;
|
||||
|
||||
std::vector<TextureBinding> textureBindings;
|
||||
std::vector<BufferBinding> bufferBindings;
|
||||
|
||||
std::unordered_map<RenderPipelineKey, const void *, RenderPipelineHasher> cachedRenderPipelines;
|
||||
|
||||
|
||||
@@ -227,6 +227,11 @@ static inline id<MTLTexture> getMTLTexture(love::graphics::Texture *tex)
|
||||
return tex ? (__bridge id<MTLTexture>)(void *) tex->getHandle() : nil;
|
||||
}
|
||||
|
||||
static inline id<MTLTexture> getMTLTexture(love::graphics::Buffer *buffer)
|
||||
{
|
||||
return buffer ? (__bridge id<MTLTexture>)(void *) buffer->getTexelBufferHandle() : nil;
|
||||
}
|
||||
|
||||
static inline id<MTLSamplerState> getMTLSampler(love::graphics::Texture *tex)
|
||||
{
|
||||
return tex ? (__bridge id<MTLSamplerState>)(void *) tex->getSamplerHandle() : nil;
|
||||
@@ -385,12 +390,28 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
{
|
||||
const SPIRType &basetype = msl.get_type(resource.base_type_id);
|
||||
const SPIRType &type = msl.get_type(resource.type_id);
|
||||
const SPIRType &imagetype = msl.get_type(basetype.image.type);
|
||||
|
||||
UniformInfo u = {};
|
||||
u.baseType = UNIFORM_SAMPLER;
|
||||
u.name = resource.name;
|
||||
u.count = type.array.empty() ? 1 : type.array[0];
|
||||
u.location = 0;
|
||||
u.isDepthSampler = type.image.depth;
|
||||
|
||||
switch (imagetype.basetype)
|
||||
{
|
||||
case SPIRType::Float:
|
||||
u.dataBaseType = DATA_BASETYPE_FLOAT;
|
||||
break;
|
||||
case SPIRType::Int:
|
||||
u.dataBaseType = DATA_BASETYPE_INT;
|
||||
break;
|
||||
case SPIRType::UInt:
|
||||
u.dataBaseType = DATA_BASETYPE_UINT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (basetype.image.dim)
|
||||
{
|
||||
@@ -409,7 +430,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
u.textures = new love::graphics::Texture*[u.count];
|
||||
break;
|
||||
case spv::DimBuffer:
|
||||
// TODO: are texel buffers sampled images in glslang?
|
||||
u.baseType = UNIFORM_TEXELBUFFER;
|
||||
u.buffers = new love::graphics::Buffer*[u.count];
|
||||
break;
|
||||
default:
|
||||
// TODO: error? continue?
|
||||
@@ -420,7 +442,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.
|
||||
|
||||
if (u.textures != nullptr)
|
||||
if (u.baseType == UNIFORM_SAMPLER)
|
||||
{
|
||||
auto tex = gfx->getDefaultTexture(u.textureType);
|
||||
for (int i = 0; i < u.count; i++)
|
||||
@@ -429,6 +451,11 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
u.textures[i] = tex;
|
||||
}
|
||||
}
|
||||
else if (u.baseType == UNIFORM_TEXELBUFFER)
|
||||
{
|
||||
for (int i = 0; i < u.count; i++)
|
||||
u.buffers[i] = nullptr; // TODO
|
||||
}
|
||||
|
||||
uniforms[u.name] = u;
|
||||
|
||||
@@ -588,7 +615,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
msl.set_msl_options(options);
|
||||
|
||||
std::string source = msl.compile();
|
||||
// printf("// MSL SOURCE for stage %d:\n\n%s\n\n", i, source.c_str());
|
||||
// printf("// MSL SOURCE for stage %d:\n\n%s\n\n", stageindex, source.c_str());
|
||||
|
||||
NSString *nssource = [[NSString alloc] initWithBytes:source.c_str()
|
||||
length:source.length()
|
||||
@@ -625,12 +652,19 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
||||
u.ints[i] = (int)textureBindings.size();
|
||||
TextureBinding b = {};
|
||||
|
||||
b.texture = getMTLTexture(u.textures[i]);
|
||||
b.sampler = getMTLSampler(u.textures[i]);
|
||||
if (u.baseType == UNIFORM_TEXELBUFFER)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
b.texture = getMTLTexture(u.textures[i]);
|
||||
b.sampler = getMTLSampler(u.textures[i]);
|
||||
|
||||
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||
if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
|
||||
b.isMainTexture = true;
|
||||
BuiltinUniform builtin = BUILTIN_MAX_ENUM;
|
||||
if (getConstant(u.name.c_str(), builtin) && builtin == BUILTIN_TEXTURE_MAIN)
|
||||
b.isMainTexture = true;
|
||||
}
|
||||
|
||||
for (uint8 &stagebinding : b.texturestages)
|
||||
stagebinding = LOVE_UINT8_MAX;
|
||||
@@ -665,15 +699,26 @@ Shader::~Shader()
|
||||
|
||||
for (const auto &it : uniforms)
|
||||
{
|
||||
if (it.second.textures != nullptr)
|
||||
const auto &u = it.second;
|
||||
if (u.baseType == UNIFORM_SAMPLER)
|
||||
{
|
||||
free(it.second.data);
|
||||
for (int i = 0; i < it.second.count; i++)
|
||||
free(u.data);
|
||||
for (int i = 0; i < u.count; i++)
|
||||
{
|
||||
if (it.second.textures[i] != nullptr)
|
||||
it.second.textures[i]->release();
|
||||
if (u.textures[i] != nullptr)
|
||||
u.textures[i]->release();
|
||||
}
|
||||
delete[] it.second.textures;
|
||||
delete[] u.textures;
|
||||
}
|
||||
else if (u.baseType == UNIFORM_TEXELBUFFER || u.baseType == UNIFORM_STORAGEBUFFER)
|
||||
{
|
||||
free(u.data);
|
||||
for (int i = 0; i < u.count; i++)
|
||||
{
|
||||
if (u.buffers[i] != nullptr)
|
||||
u.buffers[i]->release();
|
||||
}
|
||||
delete[] u.buffers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,9 +766,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
|
||||
if (info->baseType != UNIFORM_SAMPLER)
|
||||
return;
|
||||
|
||||
bool shaderactive = current == this;
|
||||
|
||||
if (shaderactive)
|
||||
if (current == this)
|
||||
Graphics::flushBatchedDrawsGlobal();
|
||||
|
||||
count = std::min(count, info->count);
|
||||
@@ -750,6 +793,7 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
|
||||
|
||||
info->textures[i] = tex;
|
||||
|
||||
// TODO: handle changing a sampler after Shader:send(texture)...
|
||||
textureBindings[info->ints[i]].texture = getMTLTexture(tex);
|
||||
textureBindings[info->ints[i]].sampler = getMTLSampler(tex);
|
||||
}
|
||||
@@ -757,7 +801,43 @@ void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **tex
|
||||
|
||||
void Shader::sendBuffers(const UniformInfo *info, love::graphics::Buffer **buffers, int count)
|
||||
{
|
||||
// TODO
|
||||
bool texelbinding = info->baseType == UNIFORM_TEXELBUFFER;
|
||||
bool storagebinding = info->baseType == UNIFORM_STORAGEBUFFER;
|
||||
|
||||
if (!texelbinding && !storagebinding)
|
||||
return;
|
||||
|
||||
if (current == this)
|
||||
Graphics::flushBatchedDrawsGlobal();
|
||||
|
||||
count = std::min(count, info->count);
|
||||
|
||||
// Bind the textures to the texture units.
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
love::graphics::Buffer *buffer = buffers[i];
|
||||
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
if (!validateBuffer(info, buffer, false))
|
||||
continue;
|
||||
buffer->retain();
|
||||
}
|
||||
|
||||
if (info->buffers[i] != nullptr)
|
||||
info->buffers[i]->release();
|
||||
|
||||
info->buffers[i] = buffer;
|
||||
|
||||
if (texelbinding)
|
||||
{
|
||||
textureBindings[info->ints[i]].texture = getMTLTexture(buffer);
|
||||
}
|
||||
else if (storagebinding)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::setVideoTextures(love::graphics::Texture *ytexture, love::graphics::Texture *cbtexture, love::graphics::Texture *crtexture)
|
||||
|
||||
@@ -121,7 +121,7 @@ void Shader::mapActiveUniforms()
|
||||
u.location = glGetUniformLocation(program, u.name.c_str());
|
||||
u.baseType = getUniformBaseType(gltype);
|
||||
u.textureType = getUniformTextureType(gltype);
|
||||
u.texelBufferType = getUniformTexelBufferType(gltype);
|
||||
u.dataBaseType = getUniformTexelBaseType(gltype);
|
||||
u.isDepthSampler = isDepthTextureType(gltype);
|
||||
|
||||
if (u.baseType == UNIFORM_MATRIX)
|
||||
@@ -1106,7 +1106,7 @@ TextureType Shader::getUniformTextureType(GLenum type) const
|
||||
}
|
||||
}
|
||||
|
||||
DataBaseType Shader::getUniformTexelBufferType(GLenum type) const
|
||||
DataBaseType Shader::getUniformTexelBaseType(GLenum type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
@@ -92,7 +92,7 @@ private:
|
||||
MatrixSize getMatrixSize(GLenum type) const;
|
||||
UniformType getUniformBaseType(GLenum type) const;
|
||||
TextureType getUniformTextureType(GLenum type) const;
|
||||
DataBaseType getUniformTexelBufferType(GLenum type) const;
|
||||
DataBaseType getUniformTexelBaseType(GLenum type) const;
|
||||
bool isDepthTextureType(GLenum type) const;
|
||||
|
||||
void flushBatchedDraws() const;
|
||||
|
||||
Reference in New Issue
Block a user