mirror of
https://github.com/love2d/love.git
synced 2026-08-20 20:49:54 +02:00
@@ -1098,6 +1098,41 @@ bool Shader::validateBuffer(const UniformInfo *info, Buffer *buffer, bool intern
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Shader::fillUniformReflectionData(UniformInfo &u)
|
||||||
|
{
|
||||||
|
const auto &r = validationReflection;
|
||||||
|
|
||||||
|
if (u.baseType == UNIFORM_STORAGETEXTURE)
|
||||||
|
{
|
||||||
|
const auto reflectionit = r.storageTextures.find(u.name);
|
||||||
|
if (reflectionit != r.storageTextures.end())
|
||||||
|
{
|
||||||
|
u.storageTextureFormat = reflectionit->second.format;
|
||||||
|
u.access = reflectionit->second.access;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No reflection info - maybe glslang was better at detecting dead code
|
||||||
|
// than the driver's compiler?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (u.baseType == UNIFORM_STORAGEBUFFER)
|
||||||
|
{
|
||||||
|
const auto reflectionit = r.storageBuffers.find(u.name);
|
||||||
|
if (reflectionit != r.storageBuffers.end())
|
||||||
|
{
|
||||||
|
u.bufferStride = reflectionit->second.stride;
|
||||||
|
u.bufferMemberCount = reflectionit->second.memberCount;
|
||||||
|
u.access = reflectionit->second.access;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Shader::initialize()
|
bool Shader::initialize()
|
||||||
{
|
{
|
||||||
return glslang::InitializeProcess();
|
return glslang::InitializeProcess();
|
||||||
|
|||||||
@@ -289,6 +289,8 @@ protected:
|
|||||||
bool usesPointSize;
|
bool usesPointSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool fillUniformReflectionData(UniformInfo &u);
|
||||||
|
|
||||||
static bool validateInternal(StrongRef<ShaderStage> stages[], std::string& err, ValidationReflection &reflection);
|
static bool validateInternal(StrongRef<ShaderStage> stages[], std::string& err, ValidationReflection &reflection);
|
||||||
static DataBaseType getDataBaseType(PixelFormat format);
|
static DataBaseType getDataBaseType(PixelFormat format);
|
||||||
static bool isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b);
|
static bool isResourceBaseTypeCompatible(DataBaseType a, DataBaseType b);
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ private:
|
|||||||
|
|
||||||
id<MTLDepthStencilState> getCachedDepthStencilState(const DepthState &depth, const StencilState &stencil);
|
id<MTLDepthStencilState> getCachedDepthStencilState(const DepthState &depth, const StencilState &stencil);
|
||||||
void applyRenderState(id<MTLRenderCommandEncoder> renderEncoder, const VertexAttributes &attributes);
|
void applyRenderState(id<MTLRenderCommandEncoder> renderEncoder, const VertexAttributes &attributes);
|
||||||
void applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::graphics::Shader *shader);
|
bool applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::graphics::Shader *shader);
|
||||||
void applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, love::graphics::Shader *shader, Texture *maintex);
|
void applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, love::graphics::Shader *shader, Texture *maintex);
|
||||||
|
|
||||||
id<MTLCommandQueue> commandQueue;
|
id<MTLCommandQueue> commandQueue;
|
||||||
|
|||||||
@@ -947,7 +947,7 @@ void Graphics::applyRenderState(id<MTLRenderCommandEncoder> encoder, const Verte
|
|||||||
dirtyRenderState = 0;
|
dirtyRenderState = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::graphics::Shader *shader)
|
bool Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::graphics::Shader *shader)
|
||||||
{
|
{
|
||||||
Shader *s = (Shader *)shader;
|
Shader *s = (Shader *)shader;
|
||||||
|
|
||||||
@@ -982,6 +982,8 @@ void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
|||||||
|
|
||||||
uniformBufferOffset += alignUp(size, alignment);
|
uniformBufferOffset += alignUp(size, alignment);
|
||||||
|
|
||||||
|
bool allWritableVariablesSet = true;
|
||||||
|
|
||||||
for (const Shader::TextureBinding &b : s->getTextureBindings())
|
for (const Shader::TextureBinding &b : s->getTextureBindings())
|
||||||
{
|
{
|
||||||
id<MTLTexture> texture = b.texture;
|
id<MTLTexture> texture = b.texture;
|
||||||
@@ -991,7 +993,12 @@ void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
|||||||
uint8 sampindex = b.samplerStages[SHADERSTAGE_COMPUTE];
|
uint8 sampindex = b.samplerStages[SHADERSTAGE_COMPUTE];
|
||||||
|
|
||||||
if (texindex != LOVE_UINT8_MAX)
|
if (texindex != LOVE_UINT8_MAX)
|
||||||
|
{
|
||||||
setTexture(encoder, bindings, texindex, texture);
|
setTexture(encoder, bindings, texindex, texture);
|
||||||
|
if ((b.access & Shader::ACCESS_WRITE) != 0 && texture == nil)
|
||||||
|
allWritableVariablesSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sampindex != LOVE_UINT8_MAX)
|
if (sampindex != LOVE_UINT8_MAX)
|
||||||
setSampler(encoder, bindings, sampindex, samplertex);
|
setSampler(encoder, bindings, sampindex, samplertex);
|
||||||
}
|
}
|
||||||
@@ -1000,10 +1007,16 @@ void Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
|||||||
{
|
{
|
||||||
uint8 index = b.stages[SHADERSTAGE_COMPUTE];
|
uint8 index = b.stages[SHADERSTAGE_COMPUTE];
|
||||||
if (index != LOVE_UINT8_MAX)
|
if (index != LOVE_UINT8_MAX)
|
||||||
|
{
|
||||||
setBuffer(encoder, bindings, index, b.buffer, 0);
|
setBuffer(encoder, bindings, index, b.buffer, 0);
|
||||||
|
if ((b.access & Shader::ACCESS_WRITE) != 0 && b.buffer == nil)
|
||||||
|
allWritableVariablesSet = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return allWritableVariablesSet;
|
||||||
|
}
|
||||||
|
|
||||||
void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, love::graphics::Shader *shader, love::graphics::Texture *maintex)
|
void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, love::graphics::Shader *shader, love::graphics::Texture *maintex)
|
||||||
{
|
{
|
||||||
Shader *s = (Shader *)shader;
|
Shader *s = (Shader *)shader;
|
||||||
@@ -1299,7 +1312,8 @@ bool Graphics::dispatch(int x, int y, int z)
|
|||||||
|
|
||||||
id<MTLComputeCommandEncoder> computeEncoder = useComputeEncoder();
|
id<MTLComputeCommandEncoder> computeEncoder = useComputeEncoder();
|
||||||
|
|
||||||
applyShaderUniforms(computeEncoder, shader);
|
if (!applyShaderUniforms(computeEncoder, shader))
|
||||||
|
return false;
|
||||||
|
|
||||||
// TODO: track this state?
|
// TODO: track this state?
|
||||||
[computeEncoder setComputePipelineState:pipeline];
|
[computeEncoder setComputePipelineState:pipeline];
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ namespace spirv_cross
|
|||||||
{
|
{
|
||||||
class CompilerMSL;
|
class CompilerMSL;
|
||||||
struct SPIRType;
|
struct SPIRType;
|
||||||
|
struct Resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
@@ -86,6 +87,7 @@ public:
|
|||||||
Texture *samplerTexture;
|
Texture *samplerTexture;
|
||||||
|
|
||||||
bool isMainTexture;
|
bool isMainTexture;
|
||||||
|
Access access;
|
||||||
|
|
||||||
uint8 textureStages[SHADERSTAGE_MAX_ENUM];
|
uint8 textureStages[SHADERSTAGE_MAX_ENUM];
|
||||||
uint8 samplerStages[SHADERSTAGE_MAX_ENUM];
|
uint8 samplerStages[SHADERSTAGE_MAX_ENUM];
|
||||||
@@ -95,6 +97,7 @@ public:
|
|||||||
{
|
{
|
||||||
id<MTLBuffer> buffer;
|
id<MTLBuffer> buffer;
|
||||||
uint8 stages[SHADERSTAGE_MAX_ENUM];
|
uint8 stages[SHADERSTAGE_MAX_ENUM];
|
||||||
|
Access access;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]);
|
Shader(id<MTLDevice> device, StrongRef<love::graphics::ShaderStage> stages[SHADERSTAGE_MAX_ENUM]);
|
||||||
@@ -137,6 +140,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename);
|
void buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv_cross::SPIRType &type, size_t baseoffset, const std::string &basename);
|
||||||
|
void addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Resource &resource, UniformType baseType);
|
||||||
void compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program);
|
void compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program);
|
||||||
|
|
||||||
id<MTLFunction> functions[SHADERSTAGE_MAX_ENUM];
|
id<MTLFunction> functions[SHADERSTAGE_MAX_ENUM];
|
||||||
|
|||||||
@@ -455,63 +455,28 @@ void Shader::buildLocalUniforms(const spirv_cross::CompilerMSL &msl, const spirv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program)
|
void Shader::addImage(const spirv_cross::CompilerMSL &msl, const spirv_cross::Resource &resource, UniformType baseType)
|
||||||
{
|
{
|
||||||
using namespace glslang;
|
|
||||||
using namespace spirv_cross;
|
using namespace spirv_cross;
|
||||||
|
|
||||||
auto gfx = Graphics::getInstance();
|
|
||||||
|
|
||||||
std::map<std::string, int> varyings;
|
|
||||||
int nextVaryingLocation = 0;
|
|
||||||
|
|
||||||
int metalBufferIndices[SHADERSTAGE_MAX_ENUM];
|
|
||||||
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
|
|
||||||
metalBufferIndices[i] = getUniformBufferBinding() + 1;
|
|
||||||
metalBufferIndices[SHADERSTAGE_VERTEX] = DEFAULT_VERTEX_BUFFER_BINDING + 1;
|
|
||||||
|
|
||||||
for (int stageindex = 0; stageindex < SHADERSTAGE_MAX_ENUM; stageindex++)
|
|
||||||
{
|
|
||||||
auto glslangstage = getGLSLangStage((ShaderStageType) stageindex);
|
|
||||||
auto intermediate = program.getIntermediate(glslangstage);
|
|
||||||
if (intermediate == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
spv::SpvBuildLogger logger;
|
|
||||||
glslang::SpvOptions opt;
|
|
||||||
opt.validate = true;
|
|
||||||
|
|
||||||
std::vector<unsigned int> spirv;
|
|
||||||
GlslangToSpv(*intermediate, spirv, &logger, &opt);
|
|
||||||
|
|
||||||
std::string msgs = logger.getAllMessages();
|
|
||||||
// printf("spirv length: %ld, messages:\n%s\n", spirv.size(), msgs.c_str());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// printf("GLSL INPUT SOURCE:\n\n%s\n\n", pixel->getSource().c_str());
|
|
||||||
|
|
||||||
CompilerMSL msl(std::move(spirv));
|
|
||||||
|
|
||||||
auto interfacevars = msl.get_active_interface_variables();
|
|
||||||
|
|
||||||
msl.set_enabled_interface_variables(interfacevars);
|
|
||||||
|
|
||||||
ShaderResources resources = msl.get_shader_resources();
|
|
||||||
|
|
||||||
for (const auto &resource : resources.sampled_images)
|
|
||||||
{
|
|
||||||
const SPIRType &basetype = msl.get_type(resource.base_type_id);
|
const SPIRType &basetype = msl.get_type(resource.base_type_id);
|
||||||
const SPIRType &type = msl.get_type(resource.type_id);
|
const SPIRType &type = msl.get_type(resource.type_id);
|
||||||
const SPIRType &imagetype = msl.get_type(basetype.image.type);
|
const SPIRType &imagetype = msl.get_type(basetype.image.type);
|
||||||
|
|
||||||
UniformInfo u = {};
|
UniformInfo u = {};
|
||||||
u.baseType = UNIFORM_SAMPLER;
|
u.baseType = baseType;
|
||||||
u.name = resource.name;
|
u.name = resource.name;
|
||||||
u.count = type.array.empty() ? 1 : type.array[0];
|
u.count = type.array.empty() ? 1 : type.array[0];
|
||||||
u.isDepthSampler = type.image.depth;
|
u.isDepthSampler = type.image.depth;
|
||||||
u.components = 1;
|
u.components = 1;
|
||||||
|
|
||||||
|
auto it = uniforms.find(u.name);
|
||||||
|
if (it != uniforms.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!fillUniformReflectionData(u))
|
||||||
|
return;
|
||||||
|
|
||||||
switch (imagetype.basetype)
|
switch (imagetype.basetype)
|
||||||
{
|
{
|
||||||
case SPIRType::Float:
|
case SPIRType::Float:
|
||||||
@@ -559,7 +524,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
|
|
||||||
if (u.baseType == UNIFORM_SAMPLER)
|
if (u.baseType == UNIFORM_SAMPLER)
|
||||||
{
|
{
|
||||||
auto tex = gfx->getDefaultTexture(u.textureType);
|
auto tex = Graphics::getInstance()->getDefaultTexture(u.textureType);
|
||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
{
|
{
|
||||||
tex->retain();
|
tex->retain();
|
||||||
@@ -571,6 +536,11 @@ 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.buffers[i] = nullptr; // TODO
|
u.buffers[i] = nullptr; // TODO
|
||||||
}
|
}
|
||||||
|
else if (u.baseType == UNIFORM_STORAGETEXTURE)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < u.count; i++)
|
||||||
|
u.textures[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
uniforms[u.name] = u;
|
uniforms[u.name] = u;
|
||||||
|
|
||||||
@@ -579,6 +549,58 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
builtinUniformInfo[builtin] = &uniforms[u.name];
|
builtinUniformInfo[builtin] = &uniforms[u.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &program)
|
||||||
|
{
|
||||||
|
using namespace glslang;
|
||||||
|
using namespace spirv_cross;
|
||||||
|
|
||||||
|
std::map<std::string, int> varyings;
|
||||||
|
int nextVaryingLocation = 0;
|
||||||
|
|
||||||
|
int metalBufferIndices[SHADERSTAGE_MAX_ENUM];
|
||||||
|
for (int i = 0; i < SHADERSTAGE_MAX_ENUM; i++)
|
||||||
|
metalBufferIndices[i] = getUniformBufferBinding() + 1;
|
||||||
|
metalBufferIndices[SHADERSTAGE_VERTEX] = DEFAULT_VERTEX_BUFFER_BINDING + 1;
|
||||||
|
|
||||||
|
for (int stageindex = 0; stageindex < SHADERSTAGE_MAX_ENUM; stageindex++)
|
||||||
|
{
|
||||||
|
auto glslangstage = getGLSLangStage((ShaderStageType) stageindex);
|
||||||
|
auto intermediate = program.getIntermediate(glslangstage);
|
||||||
|
if (intermediate == nullptr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
spv::SpvBuildLogger logger;
|
||||||
|
glslang::SpvOptions opt;
|
||||||
|
opt.validate = true;
|
||||||
|
|
||||||
|
std::vector<unsigned int> spirv;
|
||||||
|
GlslangToSpv(*intermediate, spirv, &logger, &opt);
|
||||||
|
|
||||||
|
std::string msgs = logger.getAllMessages();
|
||||||
|
// printf("spirv length: %ld, messages:\n%s\n", spirv.size(), msgs.c_str());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// printf("GLSL INPUT SOURCE:\n\n%s\n\n", pixel->getSource().c_str());
|
||||||
|
|
||||||
|
CompilerMSL msl(std::move(spirv));
|
||||||
|
|
||||||
|
auto interfacevars = msl.get_active_interface_variables();
|
||||||
|
|
||||||
|
msl.set_enabled_interface_variables(interfacevars);
|
||||||
|
|
||||||
|
ShaderResources resources = msl.get_shader_resources();
|
||||||
|
|
||||||
|
for (const auto &resource : resources.storage_images)
|
||||||
|
{
|
||||||
|
addImage(msl, resource, UNIFORM_STORAGETEXTURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &resource : resources.sampled_images)
|
||||||
|
{
|
||||||
|
addImage(msl, resource, UNIFORM_SAMPLER);
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto &resource : resources.uniform_buffers)
|
for (const auto &resource : resources.uniform_buffers)
|
||||||
{
|
{
|
||||||
MSLResourceBinding binding;
|
MSLResourceBinding binding;
|
||||||
@@ -639,19 +661,8 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
u.name = resource.name;
|
u.name = resource.name;
|
||||||
u.count = type.array.empty() ? 1 : type.array[0];
|
u.count = type.array.empty() ? 1 : type.array[0];
|
||||||
|
|
||||||
const auto reflectionit = validationReflection.storageBuffers.find(u.name);
|
if (!fillUniformReflectionData(u))
|
||||||
if (reflectionit != validationReflection.storageBuffers.end())
|
|
||||||
{
|
|
||||||
u.bufferStride = reflectionit->second.stride;
|
|
||||||
u.bufferMemberCount = reflectionit->second.memberCount;
|
|
||||||
u.access = reflectionit->second.access;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No reflection info - maybe glslang was better at detecting
|
|
||||||
// dead code than the driver's compiler?
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
u.buffers = new love::graphics::Buffer*[u.count];
|
u.buffers = new love::graphics::Buffer*[u.count];
|
||||||
u.dataSize = sizeof(int) * u.count;
|
u.dataSize = sizeof(int) * u.count;
|
||||||
@@ -741,11 +752,11 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
|
|
||||||
functions[stageindex] = [library newFunctionWithName:library.functionNames[0]];
|
functions[stageindex] = [library newFunctionWithName:library.functionNames[0]];
|
||||||
|
|
||||||
for (const auto &resource : resources.sampled_images)
|
auto setTextureBinding = [this](CompilerMSL &msl, int stageindex, const spirv_cross::Resource &resource) -> void
|
||||||
{
|
{
|
||||||
auto it = uniforms.find(resource.name);
|
auto it = uniforms.find(resource.name);
|
||||||
if (it == uniforms.end())
|
if (it == uniforms.end())
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
UniformInfo &u = it->second;
|
UniformInfo &u = it->second;
|
||||||
|
|
||||||
@@ -753,7 +764,7 @@ 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)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
{
|
{
|
||||||
@@ -761,6 +772,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
{
|
{
|
||||||
u.ints[i] = (int)textureBindings.size();
|
u.ints[i] = (int)textureBindings.size();
|
||||||
TextureBinding b = {};
|
TextureBinding b = {};
|
||||||
|
b.access = u.access;
|
||||||
|
|
||||||
if (u.baseType == UNIFORM_TEXELBUFFER)
|
if (u.baseType == UNIFORM_TEXELBUFFER)
|
||||||
{
|
{
|
||||||
@@ -788,6 +800,16 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
b.textureStages[stageindex] = (uint8) texturebinding;
|
b.textureStages[stageindex] = (uint8) texturebinding;
|
||||||
b.samplerStages[stageindex] = (uint8) samplerbinding;
|
b.samplerStages[stageindex] = (uint8) samplerbinding;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &resource : resources.sampled_images)
|
||||||
|
{
|
||||||
|
setTextureBinding(msl, stageindex, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &resource : resources.storage_images)
|
||||||
|
{
|
||||||
|
setTextureBinding(msl, stageindex, resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &resource : resources.storage_buffers)
|
for (const auto &resource : resources.storage_buffers)
|
||||||
@@ -808,6 +830,7 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
|
|||||||
{
|
{
|
||||||
u.ints[i] = (int)bufferBindings.size();
|
u.ints[i] = (int)bufferBindings.size();
|
||||||
BufferBinding b = {};
|
BufferBinding b = {};
|
||||||
|
b.access = u.access;
|
||||||
|
|
||||||
for (uint8 &stagebinding : b.stages)
|
for (uint8 &stagebinding : b.stages)
|
||||||
stagebinding = LOVE_UINT8_MAX;
|
stagebinding = LOVE_UINT8_MAX;
|
||||||
@@ -841,7 +864,7 @@ Shader::~Shader()
|
|||||||
for (const auto &it : uniforms)
|
for (const auto &it : uniforms)
|
||||||
{
|
{
|
||||||
const auto &u = it.second;
|
const auto &u = it.second;
|
||||||
if (u.baseType == UNIFORM_SAMPLER)
|
if (u.baseType == UNIFORM_SAMPLER || u.baseType == UNIFORM_STORAGETEXTURE)
|
||||||
{
|
{
|
||||||
free(u.data);
|
free(u.data);
|
||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
@@ -940,7 +963,7 @@ void Shader::updateUniform(const UniformInfo *info, int count)
|
|||||||
|
|
||||||
void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count)
|
void Shader::sendTextures(const UniformInfo *info, love::graphics::Texture **textures, int count)
|
||||||
{ @autoreleasepool {
|
{ @autoreleasepool {
|
||||||
if (info->baseType != UNIFORM_SAMPLER)
|
if (info->baseType != UNIFORM_SAMPLER && info->baseType != UNIFORM_STORAGETEXTURE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (current == this)
|
if (current == this)
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ void Shader::mapActiveUniforms()
|
|||||||
if (u.location == -1)
|
if (u.location == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!fillUniformReflectionData(u))
|
||||||
|
continue;;
|
||||||
|
|
||||||
if ((u.baseType == UNIFORM_SAMPLER && builtin != BUILTIN_TEXTURE_MAIN) || u.baseType == UNIFORM_TEXELBUFFER)
|
if ((u.baseType == UNIFORM_SAMPLER && builtin != BUILTIN_TEXTURE_MAIN) || u.baseType == UNIFORM_TEXELBUFFER)
|
||||||
{
|
{
|
||||||
TextureUnit unit;
|
TextureUnit unit;
|
||||||
@@ -161,19 +164,6 @@ void Shader::mapActiveUniforms()
|
|||||||
}
|
}
|
||||||
else if (u.baseType == UNIFORM_STORAGETEXTURE)
|
else if (u.baseType == UNIFORM_STORAGETEXTURE)
|
||||||
{
|
{
|
||||||
const auto reflectionit = validationReflection.storageTextures.find(u.name);
|
|
||||||
if (reflectionit != validationReflection.storageTextures.end())
|
|
||||||
{
|
|
||||||
u.storageTextureFormat = reflectionit->second.format;
|
|
||||||
u.access = reflectionit->second.access;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No reflection info - maybe glslang was better at detecting
|
|
||||||
// dead code than the driver's compiler?
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
StorageTextureBinding binding = {};
|
StorageTextureBinding binding = {};
|
||||||
binding.gltexture = gl.getDefaultTexture(u.textureType, u.dataBaseType);
|
binding.gltexture = gl.getDefaultTexture(u.textureType, u.dataBaseType);
|
||||||
binding.type = u.textureType;
|
binding.type = u.textureType;
|
||||||
@@ -373,19 +363,8 @@ void Shader::mapActiveUniforms()
|
|||||||
u.name = std::string(namebuffer, namelength);
|
u.name = std::string(namebuffer, namelength);
|
||||||
u.count = 1;
|
u.count = 1;
|
||||||
|
|
||||||
const auto reflectionit = validationReflection.storageBuffers.find(u.name);
|
if (!fillUniformReflectionData(u))
|
||||||
if (reflectionit != validationReflection.storageBuffers.end())
|
|
||||||
{
|
|
||||||
u.bufferStride = reflectionit->second.stride;
|
|
||||||
u.bufferMemberCount = reflectionit->second.memberCount;
|
|
||||||
u.access = reflectionit->second.access;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No reflection info - maybe glslang was better at detecting
|
|
||||||
// dead code than the driver's compiler?
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure previously set uniform data is preserved, and shader-
|
// Make sure previously set uniform data is preserved, and shader-
|
||||||
// initialized values are retrieved.
|
// initialized values are retrieved.
|
||||||
|
|||||||
@@ -872,18 +872,11 @@ void Shader::compileShaders()
|
|||||||
u.components = 1;
|
u.components = 1;
|
||||||
u.name = r.name;
|
u.name = r.name;
|
||||||
u.count = type.array.empty() ? 1 : type.array[0];
|
u.count = type.array.empty() ? 1 : type.array[0];
|
||||||
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
|
|
||||||
|
|
||||||
const auto reflectionit = validationReflection.storageBuffers.find(u.name);
|
if (!fillUniformReflectionData(u))
|
||||||
if (reflectionit != validationReflection.storageBuffers.end())
|
|
||||||
{
|
|
||||||
u.bufferStride = reflectionit->second.stride;
|
|
||||||
u.bufferMemberCount = reflectionit->second.memberCount;
|
|
||||||
u.access = reflectionit->second.access;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
|
||||||
u.buffers = new love::graphics::Buffer *[u.count];
|
u.buffers = new love::graphics::Buffer *[u.count];
|
||||||
|
|
||||||
for (int i = 0; i < u.count; i++)
|
for (int i = 0; i < u.count; i++)
|
||||||
@@ -901,6 +894,10 @@ void Shader::compileShaders()
|
|||||||
u.components = 1;
|
u.components = 1;
|
||||||
u.name = r.name;
|
u.name = r.name;
|
||||||
u.count = type.array.empty() ? 1 : type.array[0];
|
u.count = type.array.empty() ? 1 : type.array[0];
|
||||||
|
|
||||||
|
if (!fillUniformReflectionData(u))
|
||||||
|
continue;
|
||||||
|
|
||||||
u.textures = new love::graphics::Texture *[u.count];
|
u.textures = new love::graphics::Texture *[u.count];
|
||||||
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
|
u.location = comp.get_decoration(r.id, spv::DecorationBinding);
|
||||||
|
|
||||||
@@ -913,6 +910,7 @@ void Shader::compileShaders()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shaderStage == SHADERSTAGE_VERTEX)
|
if (shaderStage == SHADERSTAGE_VERTEX)
|
||||||
|
{
|
||||||
for (const auto &r : shaderResources.stage_inputs)
|
for (const auto &r : shaderResources.stage_inputs)
|
||||||
{
|
{
|
||||||
const auto &name = r.name;
|
const auto &name = r.name;
|
||||||
@@ -920,6 +918,7 @@ void Shader::compileShaders()
|
|||||||
attributes[name] = attributeLocation;
|
attributes[name] = attributeLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete program;
|
delete program;
|
||||||
for (auto shader : glslangShaders)
|
for (auto shader : glslangShaders)
|
||||||
|
|||||||
Reference in New Issue
Block a user