metal: initial texel buffer Shader:send implementation

This commit is contained in:
Alex Szpakowski
2021-03-31 23:02:36 -03:00
parent 1b9b32c7a7
commit 5fa570b9a6
7 changed files with 114 additions and 26 deletions
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -124,8 +124,8 @@ public:
};
UniformType baseType;
DataBaseType dataBaseType;
TextureType textureType;
DataBaseType texelBufferType;
bool isDepthSampler;
size_t bufferStride;
size_t bufferMemberCount;
+1 -1
View File
@@ -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];
+8
View File
@@ -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;
+99 -19
View File
@@ -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)
+2 -2
View File
@@ -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)
{
+1 -1
View File
@@ -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;