Browse Source

metal: fix vertex attribute locations not being set correctly.

Sasha Szpakowski 11 months ago
parent
commit
2c288715d4
1 changed files with 31 additions and 11 deletions
  1. 31 11
      src/modules/graphics/metal/Shader.mm

+ 31 - 11
src/modules/graphics/metal/Shader.mm

@@ -453,24 +453,44 @@ void Shader::compileFromGLSLang(id<MTLDevice> device, const glslang::TProgram &p
 
 
 		if (stageindex == SHADERSTAGE_VERTEX)
 		if (stageindex == SHADERSTAGE_VERTEX)
 		{
 		{
-			int nextattributeindex = ATTRIB_MAX_ENUM;
+			uint64 usedInputLocationBits = 0;
 
 
+			// First pass: record active input locations that were set to a valid value
+			// beforehand.
 			for (const auto &var : interfacevars)
 			for (const auto &var : interfacevars)
 			{
 			{
-				spv::StorageClass storage = msl.get_storage_class(var);
-				const std::string &name = msl.get_name(var);
+				if (msl.get_storage_class(var) == spv::StorageClassInput)
+				{
+					const std::string &name = msl.get_name(var);
+
+					auto it = reflection.vertexInputs.find(name);
+					if (it != reflection.vertexInputs.end() && it->second >= 0)
+						usedInputLocationBits |= (1ull << it->second);
+				}
+			}
 
 
-				if (storage == spv::StorageClassInput)
+			// Second pass: set input locations which were not part of the above pass,
+			// they need to not overlap. And then store all input locations for later use.
+			for (const auto &var : interfacevars)
+			{
+				if (msl.get_storage_class(var) == spv::StorageClassInput)
 				{
 				{
-					int index = 0;
+					const std::string &name = msl.get_name(var);
 
 
-					BuiltinVertexAttribute builtinattribute;
-					if (graphics::getConstant(name.c_str(), builtinattribute))
-						index = (int) builtinattribute;
-					else
-						index = nextattributeindex++;
+					auto it = reflection.vertexInputs.find(name);
+					if (it == reflection.vertexInputs.end() || it->second < 0)
+					{
+						for (int i = 0; i < 64; i++)
+						{
+							if ((usedInputLocationBits & (1ull << i)) == 0)
+							{
+								usedInputLocationBits |= (1ull << i);
+								msl.set_decoration(var, spv::DecorationLocation, i);
+								break;
+							}
+						}
+					}
 
 
-					msl.set_decoration(var, spv::DecorationLocation, index);
 					attributes[name] = msl.get_decoration(var, spv::DecorationLocation);
 					attributes[name] = msl.get_decoration(var, spv::DecorationLocation);
 				}
 				}
 			}
 			}