Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix same uniforms in fragment and vertex shaders not working in Metal #1808

Merged
merged 5 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 12 additions & 30 deletions core/renderer/backend/ProgramState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,10 @@ void ProgramState::setCallbackUniform(const backend::UniformLocation& uniformLoc

void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, const void* data, std::size_t size)
{
switch (uniformLocation.shaderStage)
{
case backend::ShaderStage::VERTEX:
setVertexUniform(uniformLocation.location[0], data, size, uniformLocation.location[1]);
break;
case backend::ShaderStage::FRAGMENT:
setFragmentUniform(uniformLocation.location[0], data, size, uniformLocation.location[1]);
break;
default:;
}
if (uniformLocation.vertStage)
setVertexUniform(uniformLocation.vertStage.location, data, size, uniformLocation.vertStage.offset);
if (uniformLocation.fragStage)
smilediver marked this conversation as resolved.
Show resolved Hide resolved
setFragmentUniform(uniformLocation.fragStage.location, data, size, uniformLocation.fragStage.offset);
}

void ProgramState::setVertexUniform(int location, const void* data, std::size_t size, std::size_t offset)
Expand Down Expand Up @@ -337,32 +331,20 @@ void ProgramState::setTexture(const backend::UniformLocation& uniformLocation,
int index,
backend::TextureBackend* texture)
{
switch (uniformLocation.shaderStage)
{
case backend::ShaderStage::VERTEX:
setTexture(uniformLocation.location[0], slot, index, texture, _vertexTextureInfos);
break;
case backend::ShaderStage::FRAGMENT:
setTexture(uniformLocation.location[0], slot, index, texture, _fragmentTextureInfos);
break;
default:;
}
if (uniformLocation.vertStage)
setTexture(uniformLocation.vertStage.location, slot, index, texture, _vertexTextureInfos);
if (uniformLocation.fragStage)
setTexture(uniformLocation.fragStage.location, slot, index, texture, _fragmentTextureInfos);
}

void ProgramState::setTextureArray(const backend::UniformLocation& uniformLocation,
std::vector<int> slots,
std::vector<backend::TextureBackend*> textures)
{
switch (uniformLocation.shaderStage)
{
case backend::ShaderStage::VERTEX:
setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _vertexTextureInfos);
break;
case backend::ShaderStage::FRAGMENT:
setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _fragmentTextureInfos);
break;
default:;
}
if (uniformLocation.vertStage)
setTextureArray(uniformLocation.vertStage.location, std::move(slots), std::move(textures), _vertexTextureInfos);
if (uniformLocation.fragStage)
setTextureArray(uniformLocation.fragStage.location, std::move(slots), std::move(textures), _fragmentTextureInfos);
}

void ProgramState::setTexture(int location,
Expand Down
10 changes: 8 additions & 2 deletions core/renderer/backend/Types.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md).

https://axmolengine.github.io/

Expand All @@ -26,14 +27,19 @@

NS_AX_BACKEND_BEGIN

bool StageUniformLocation::operator==(const StageUniformLocation& other) const
{
return location == other.location && offset == other.offset;
}

bool UniformLocation::operator==(const UniformLocation& other) const
{
return (shaderStage == other.shaderStage && location[0] == other.location[0] && location[1] == other.location[1]);
return vertStage == other.vertStage && fragStage == other.fragStage;
}

std::size_t UniformLocation::operator()(const UniformLocation& uniform) const
{
return (((size_t)shaderStage) & 0xF) | ((size_t)(location[0] << 4)) | ((size_t)(location[1] << 8));
return size_t(vertStage.location) ^ size_t(fragStage.location << 16);
}

NS_AX_BACKEND_END
36 changes: 15 additions & 21 deletions core/renderer/backend/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,30 +76,24 @@ struct UniformInfo
unsigned int bufferOffset = 0;
};

struct StageUniformLocation
{
int location = -1;
int offset = -1;

operator bool() const { return location != -1; }
bool operator==(const StageUniformLocation& other) const;
};

struct UniformLocation
{
UniformLocation()
{
location[0] = -1;
location[1] = -1;
shaderStage = ShaderStage::UNKNOWN;
}
UniformLocation(int loc, int offset, ShaderStage stage = ShaderStage::VERTEX)
{
location[0] = loc;
location[1] = offset;
shaderStage = stage;
}
/**
* both opengl and metal, location[0] represent the location, and location[1] represent location offset in uniform
* block.
*/
int location[2];
ShaderStage shaderStage;
operator bool() { return shaderStage != ShaderStage::UNKNOWN; }
void reset() { location[0] = location[1] = -1; }
StageUniformLocation vertStage;
StageUniformLocation fragStage;

operator bool() const { return vertStage or fragStage; }
void reset() { vertStage = {}; fragStage = {}; }
bool operator==(const UniformLocation& other) const;
std::size_t operator()(const UniformLocation& uniform) const;
std::size_t operator()(const UniformLocation& uniform) const; // used as a hash function
};

struct AttributeBindInfo
Expand Down
28 changes: 18 additions & 10 deletions core/renderer/backend/metal/ProgramMTL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,28 @@ of this software and associated documentation files (the "Software"), to deal

UniformLocation ProgramMTL::getUniformLocation(backend::Uniform name) const
{
UniformLocation uniformLocation;
uniformLocation = _vertexShader->getUniformLocation(name);
if (uniformLocation.location[0] != -1)
return uniformLocation;
return _fragmentShader->getUniformLocation(name);
auto& vert = _vertexShader->getUniformInfo(name);
auto& frag = _fragmentShader->getUniformInfo(name);

return UniformLocation {
{ vert.location, vert.location == -1 ? -1 : static_cast<int>(vert.bufferOffset) },
{ frag.location, frag.location == -1 ? -1 : static_cast<int>(frag.bufferOffset) }
};
}

UniformLocation ProgramMTL::getUniformLocation(std::string_view uniform) const
{
UniformLocation uniformLocation;
uniformLocation = _vertexShader->getUniformLocation(uniform);
if (uniformLocation.location[0] != -1)
return uniformLocation;
return _fragmentShader->getUniformLocation(uniform);
auto& vert = _vertexShader->getUniformInfo(uniform);
auto& frag = _fragmentShader->getUniformInfo(uniform);

if (vert.location != -1 && frag.location != -1)
AXASSERT(vert.type == frag.type && vert.count == frag.count && vert.size == frag.size,
"Same vertex and fragment uniform must much in type and size");

return UniformLocation {
{ vert.location, vert.location == -1 ? -1 : static_cast<int>(vert.bufferOffset) },
{ frag.location, frag.location == -1 ? -1 : static_cast<int>(frag.bufferOffset) }
};
}

int ProgramMTL::getMaxVertexLocation() const
Expand Down
12 changes: 6 additions & 6 deletions core/renderer/backend/metal/ShaderModuleMTL.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,18 @@ class ShaderModuleMTL : public ShaderModule
inline const hlookup::string_map<AttributeBindInfo>& getAttributeInfo() const { return _attributeInfo; }

/**
* Get uniform location by engine built-in uniform enum name.
* Get uniform info by engine built-in uniform enum name.
* @param name Specifies the engine built-in uniform enum name.
* @return The uniform location.
*/
UniformLocation getUniformLocation(Uniform name) const;
const UniformInfo& getUniformInfo(Uniform name) const;

/**
* Get uniform location by name.
* Get uniform info by name.
* @param uniform Specifies the uniform name.
* @return The uniform location.
*/
UniformLocation getUniformLocation(std::string_view name) const;
const UniformInfo& getUniformInfo(std::string_view name) const;

/**
* Get attribute location by engine built-in attribute enum name.
Expand Down Expand Up @@ -128,8 +128,8 @@ class ShaderModuleMTL : public ShaderModule
int _attributeLocation[ATTRIBUTE_MAX];

int _maxLocation = -1;
UniformLocation _uniformLocation[UNIFORM_MAX]; // the builtin uniform locations
UniformInfo _builtinUniforms[UNIFORM_MAX];

std::size_t _uniformBufferSize = 0;
};

Expand Down
26 changes: 12 additions & 14 deletions core/renderer/backend/metal/ShaderModuleMTL.mm
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,18 @@ of this software and associated documentation files (the "Software"), to deal
}
}

UniformLocation ShaderModuleMTL::getUniformLocation(Uniform name) const
const UniformInfo& ShaderModuleMTL::getUniformInfo(Uniform name) const
{
return _uniformLocation[name];
return _builtinUniforms[name];
}

UniformLocation ShaderModuleMTL::getUniformLocation(std::string_view name) const
const UniformInfo& ShaderModuleMTL::getUniformInfo(std::string_view name) const
{
static UniformInfo none;
auto iter = _activeUniformInfos.find(name);
if (iter != _activeUniformInfos.end())
{
return UniformLocation{static_cast<int>(iter->second.location),
static_cast<int>(iter->second.bufferOffset), _stage};
}
return UniformLocation{};
return iter->second;
return none;
}

void ShaderModuleMTL::setBuiltinLocations()
Expand All @@ -295,22 +293,22 @@ of this software and associated documentation files (the "Software"), to deal
/*--- Builtin Uniforms ---*/

/// u_MVPMatrix
_uniformLocation[Uniform::MVP_MATRIX] = getUniformLocation(UNIFORM_NAME_MVP_MATRIX);
_builtinUniforms[Uniform::MVP_MATRIX] = getUniformInfo(UNIFORM_NAME_MVP_MATRIX);

/// u_tex0
_uniformLocation[Uniform::TEXTURE] = getUniformLocation(UNIFORM_NAME_TEXTURE);
_builtinUniforms[Uniform::TEXTURE] = getUniformInfo(UNIFORM_NAME_TEXTURE);

/// u_tex1
_uniformLocation[Uniform::TEXTURE1] = getUniformLocation(UNIFORM_NAME_TEXTURE1);
_builtinUniforms[Uniform::TEXTURE1] = getUniformInfo(UNIFORM_NAME_TEXTURE1);

/// u_textColor
_uniformLocation[Uniform::TEXT_COLOR] = getUniformLocation(UNIFORM_NAME_TEXT_COLOR);
_builtinUniforms[Uniform::TEXT_COLOR] = getUniformInfo(UNIFORM_NAME_TEXT_COLOR);

/// u_effectColor
_uniformLocation[Uniform::EFFECT_COLOR] = getUniformLocation(UNIFORM_NAME_EFFECT_COLOR);
_builtinUniforms[Uniform::EFFECT_COLOR] = getUniformInfo(UNIFORM_NAME_EFFECT_COLOR);

/// u_effectType
_uniformLocation[Uniform::EFFECT_TYPE] = getUniformLocation(UNIFORM_NAME_EFFECT_TYPE);
_builtinUniforms[Uniform::EFFECT_TYPE] = getUniformInfo(UNIFORM_NAME_EFFECT_TYPE);
}

int ShaderModuleMTL::getAttributeLocation(Attribute name) const
Expand Down
8 changes: 3 additions & 5 deletions core/renderer/backend/opengl/ProgramGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,15 +500,13 @@ UniformLocation ProgramGL::getUniformLocation(std::string_view uniform) const
auto iter = _activeUniformInfos.find(uniform);
if (iter != _activeUniformInfos.end())
{
uniformLocation.shaderStage = ShaderStage::VERTEX;

const auto& uniformInfo = iter->second;
#if AX_ENABLE_CACHE_TEXTURE_DATA
uniformLocation.location[0] = _mapToOriginalLocation.at(uniformInfo.location);
uniformLocation.vertStage.location = _mapToOriginalLocation.at(uniformInfo.location);
#else
uniformLocation.location[0] = uniformInfo.location;
uniformLocation.vertStage.location = uniformInfo.location;
#endif
uniformLocation.location[1] = uniformInfo.bufferOffset;
uniformLocation.vertStage.offset = uniformInfo.bufferOffset;
}

return uniformLocation;
Expand Down
28 changes: 14 additions & 14 deletions core/renderer/shaders/positionNormalTexture.vert
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ layout(location = NORMAL) out vec3 v_normal;

layout(std140) uniform vs_ub {
#ifdef USE_NORMAL_MAPPING
vec3 u_DirLightSourceDirection[MAX_DIRECTIONAL_LIGHT_NUM];
vec3 u_SpotLightSourceDirection[MAX_SPOT_LIGHT_NUM];
vvec3_def(u_DirLightSourceDirection, MAX_DIRECTIONAL_LIGHT_NUM);
vvec3_def(u_SpotLightSourceDirection, MAX_SPOT_LIGHT_NUM);
#endif
vec3 u_PointLightSourcePosition[MAX_POINT_LIGHT_NUM];
vec3 u_SpotLightSourcePosition[MAX_SPOT_LIGHT_NUM];
vvec3_def(u_PointLightSourcePosition, MAX_POINT_LIGHT_NUM);
vvec3_def(u_SpotLightSourcePosition, MAX_SPOT_LIGHT_NUM);
mat4 u_MVPMatrix;
mat4 u_MVMatrix;
mat4 u_PMatrix;
Expand All @@ -52,39 +52,39 @@ void main(void)
vec3 eNormal = normalize(u_NormalMatrix * a_normal);
for (int i = 0; i < MAX_DIRECTIONAL_LIGHT_NUM; ++i)
{
v_dirLightDirection[i].x = dot(eTangent, u_DirLightSourceDirection[i]);
v_dirLightDirection[i].y = dot(eBinormal, u_DirLightSourceDirection[i]);
v_dirLightDirection[i].z = dot(eNormal, u_DirLightSourceDirection[i]);
v_dirLightDirection[i].x = dot(eTangent, vvec3_at(u_DirLightSourceDirection, i));
v_dirLightDirection[i].y = dot(eBinormal, vvec3_at(u_DirLightSourceDirection, i));
v_dirLightDirection[i].z = dot(eNormal, vvec3_at(u_DirLightSourceDirection, i));
}

for (int i = 0; i < MAX_POINT_LIGHT_NUM; ++i)
{
vec3 pointLightDir = u_PointLightSourcePosition[i].xyz - ePosition.xyz;
vec3 pointLightDir = vvec3_at(u_PointLightSourcePosition, i).xyz - ePosition.xyz;
v_vertexToPointLightDirection[i].x = dot(eTangent, pointLightDir);
v_vertexToPointLightDirection[i].y = dot(eBinormal, pointLightDir);
v_vertexToPointLightDirection[i].z = dot(eNormal, pointLightDir);
}

for (int i = 0; i < MAX_SPOT_LIGHT_NUM; ++i)
{
vec3 spotLightDir = u_SpotLightSourcePosition[i] - ePosition.xyz;
vec3 spotLightDir = vvec3_at(u_SpotLightSourcePosition, i) - ePosition.xyz;
v_vertexToSpotLightDirection[i].x = dot(eTangent, spotLightDir);
v_vertexToSpotLightDirection[i].y = dot(eBinormal, spotLightDir);
v_vertexToSpotLightDirection[i].z = dot(eNormal, spotLightDir);

v_spotLightDirection[i].x = dot(eTangent, u_SpotLightSourceDirection[i]);
v_spotLightDirection[i].y = dot(eBinormal, u_SpotLightSourceDirection[i]);
v_spotLightDirection[i].z = dot(eNormal, u_SpotLightSourceDirection[i]);
v_spotLightDirection[i].x = dot(eTangent, vvec3_at(u_SpotLightSourceDirection, i));
v_spotLightDirection[i].y = dot(eBinormal, vvec3_at(u_SpotLightSourceDirection, i));
v_spotLightDirection[i].z = dot(eNormal, vvec3_at(u_SpotLightSourceDirection, i));
}
#else
for (int i = 0; i < MAX_POINT_LIGHT_NUM; ++i)
{
v_vertexToPointLightDirection[i] = u_PointLightSourcePosition[i].xyz - ePosition.xyz;
v_vertexToPointLightDirection[i] = vvec3_at(u_PointLightSourcePosition, i).xyz - ePosition.xyz;
}

for (int i = 0; i < MAX_SPOT_LIGHT_NUM; ++i)
{
v_vertexToSpotLightDirection[i] = u_SpotLightSourcePosition[i] - ePosition.xyz;
v_vertexToSpotLightDirection[i] = vvec3_at(u_SpotLightSourcePosition, i) - ePosition.xyz;
}

v_normal = u_NormalMatrix * a_normal;
Expand Down
Loading
Loading