Browse Source

Some work on the shader program resource

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
afe9f69ca4

+ 1 - 0
src/anki/gr/Shader.h

@@ -25,6 +25,7 @@ public:
 		I32 m_int;
 	};
 
+	U32 m_constantId = MAX_U32;
 	ShaderVariableDataType m_dataType;
 
 	ShaderSpecializationConstValue()

+ 13 - 1
src/anki/gr/vulkan/ShaderImpl.cpp

@@ -97,10 +97,22 @@ Error ShaderImpl::init(const ShaderInitInfo& inf)
 			entry.offset = count * sizeof(I32);
 			entry.size = sizeof(I32);
 
+			// Find the value
+			const ShaderSpecializationConstValue* val = nullptr;
+			for(const ShaderSpecializationConstValue& v : inf.m_constValues)
+			{
+				if(v.m_constantId == entry.constantID)
+				{
+					val = &v;
+					break;
+				}
+			}
+			ANKI_ASSERT(val && "Contant ID wasn't found in the init info");
+
 			// Copy the data
 			U8* data = static_cast<U8*>(const_cast<void*>(m_specConstInfo.pData));
 			data += entry.offset;
-			*reinterpret_cast<I32*>(data) = inf.m_constValues[sconst.constant_id].m_int;
+			*reinterpret_cast<I32*>(data) = val->m_int;
 
 			++count;
 		}

+ 223 - 65
src/anki/resource/ShaderProgramResource2.cpp

@@ -6,7 +6,9 @@
 #include <anki/resource/ShaderProgramResource2.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/gr/ShaderProgram.h>
+#include <anki/gr/GrManager.h>
 #include <anki/util/Filesystem.h>
+#include <anki/util/Functions.h>
 
 namespace anki
 {
@@ -54,96 +56,136 @@ Error ShaderProgramResource2::load(const ResourceFilename& filename, Bool async)
 	}
 
 	// Create the inputs
-	for(const ShaderProgramBinaryBlock& block : binary.m_uniformBlocks)
 	{
-		if(block.m_name.getBegin() != CString("b_ankiMaterial"))
+		U32 descriptorSet = MAX_U32;
+		U32 maxDescriptorSet = 0;
+		for(const ShaderProgramBinaryBlock& block : binary.m_uniformBlocks)
 		{
-			continue;
-		}
-
-		for(const ShaderProgramBinaryVariable& var : block.m_variables)
-		{
-			Bool instanced;
-			U32 idx;
-			CString name;
-			ANKI_CHECK(parseVariable(var.m_name.getBegin(), instanced, idx, name));
+			maxDescriptorSet = max(maxDescriptorSet, block.m_set);
 
-			if(idx > 0)
+			if(block.m_name.getBegin() != CString("b_ankiMaterial"))
 			{
 				continue;
 			}
 
-			ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
-			in.m_name.create(getAllocator(), name);
-			in.m_index = m_inputVars.getSize() - 1;
-			in.m_constant = false;
-			in.m_dataType = var.m_type;
-			in.m_instanced = instanced;
-		}
-	}
+			m_materialUboIdx = U8(&block - &binary.m_uniformBlocks[0]);
+			descriptorSet = block.m_set;
 
-	for(const ShaderProgramBinaryConstant& c : binary.m_constants)
-	{
-		U32 componentIdx;
-		U32 componentCount;
-		CString name;
-		ANKI_CHECK(parseConst(c.m_name.getBegin(), componentIdx, componentCount, name));
+			for(const ShaderProgramBinaryVariable& var : block.m_variables)
+			{
+				Bool instanced;
+				U32 idx;
+				CString name;
+				ANKI_CHECK(parseVariable(var.m_name.getBegin(), instanced, idx, name));
+
+				if(idx > 0)
+				{
+					continue;
+				}
+
+				ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
+				in.m_name.create(getAllocator(), name);
+				in.m_index = m_inputVars.getSize() - 1;
+				in.m_constant = false;
+				in.m_dataType = var.m_type;
+				in.m_instanced = instanced;
+			}
+		}
 
-		if(componentIdx > 0)
+		// Continue with the opaque if it's a material shader program
+		if(descriptorSet != MAX_U32)
 		{
-			continue;
+			for(const ShaderProgramBinaryOpaque& o : binary.m_opaques)
+			{
+				maxDescriptorSet = max(maxDescriptorSet, o.m_set);
+
+				if(o.m_set != descriptorSet)
+				{
+					continue;
+				}
+
+				ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
+				in.m_name.create(getAllocator(), o.m_name.getBegin());
+				in.m_index = m_inputVars.getSize() - 1;
+				in.m_constant = false;
+				in.m_dataType = o.m_type;
+				in.m_instanced = false;
+			}
 		}
 
-		ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
-		in.m_name.create(getAllocator(), name);
-		in.m_index = m_inputVars.getSize() - 1;
-		in.m_constant = true;
-
-		if(componentCount == 1)
+		if(descriptorSet != MAX_U32 && descriptorSet != maxDescriptorSet)
 		{
-			in.m_dataType = c.m_type;
+			ANKI_RESOURCE_LOGE("All bindings of a material shader should be in the highest descriptor set");
+			return Error::USER_DATA;
 		}
-		else if(componentCount == 2)
+
+		m_descriptorSet = U8(descriptorSet);
+
+		for(const ShaderProgramBinaryConstant& c : binary.m_constants)
 		{
-			if(c.m_type == ShaderVariableDataType::INT)
+			U32 componentIdx;
+			U32 componentCount;
+			CString name;
+			ANKI_CHECK(parseConst(c.m_name.getBegin(), componentIdx, componentCount, name));
+
+			if(componentIdx > 0)
 			{
-				in.m_dataType = ShaderVariableDataType::IVEC2;
+				continue;
 			}
-			else
+
+			ShaderProgramResourceInputVariable2& in = *m_inputVars.emplaceBack(getAllocator());
+			in.m_name.create(getAllocator(), name);
+			in.m_index = m_inputVars.getSize() - 1;
+			in.m_constant = true;
+
+			if(componentCount == 1)
 			{
-				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-				in.m_dataType = ShaderVariableDataType::VEC2;
+				in.m_dataType = c.m_type;
 			}
-		}
-		else if(componentCount == 3)
-		{
-			if(c.m_type == ShaderVariableDataType::INT)
+			else if(componentCount == 2)
 			{
-				in.m_dataType = ShaderVariableDataType::IVEC3;
+				if(c.m_type == ShaderVariableDataType::INT)
+				{
+					in.m_dataType = ShaderVariableDataType::IVEC2;
+				}
+				else
+				{
+					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+					in.m_dataType = ShaderVariableDataType::VEC2;
+				}
 			}
-			else
+			else if(componentCount == 3)
 			{
-				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-				in.m_dataType = ShaderVariableDataType::VEC3;
+				if(c.m_type == ShaderVariableDataType::INT)
+				{
+					in.m_dataType = ShaderVariableDataType::IVEC3;
+				}
+				else
+				{
+					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+					in.m_dataType = ShaderVariableDataType::VEC3;
+				}
 			}
-		}
-		else if(componentCount == 4)
-		{
-			if(c.m_type == ShaderVariableDataType::INT)
+			else if(componentCount == 4)
 			{
-				in.m_dataType = ShaderVariableDataType::IVEC4;
+				if(c.m_type == ShaderVariableDataType::INT)
+				{
+					in.m_dataType = ShaderVariableDataType::IVEC4;
+				}
+				else
+				{
+					ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
+					in.m_dataType = ShaderVariableDataType::VEC4;
+				}
 			}
 			else
 			{
-				ANKI_ASSERT(c.m_type == ShaderVariableDataType::FLOAT);
-				in.m_dataType = ShaderVariableDataType::VEC4;
+				ANKI_ASSERT(0);
 			}
 		}
-		else
-		{
-			ANKI_ASSERT(0);
-		}
-	}
+	} // End creating the inputs
+
+	m_shaderStages = binary.m_presentShaderTypes;
 
 	return Error::NONE;
 }
@@ -294,14 +336,130 @@ void ShaderProgramResource2::initVariant(
 		ANKI_ASSERT(binary.m_variants.getSize() == 1);
 		binaryVariant = &binary.m_variants[0];
 	}
-
 	ANKI_ASSERT(binaryVariant);
 
-	// XXX
-	for(const Input& in : m_inputVars)
+	// Init the uniform vars
+	if(m_materialUboIdx != MAX_U8)
 	{
-		(void)in;
+		variant.m_blockInfos.create(getAllocator(), m_inputVars.getSize());
+
+		for(const ShaderProgramBinaryVariableInstance& instance :
+			binaryVariant->m_uniformBlocks[m_materialUboIdx].m_variables)
+		{
+			ANKI_ASSERT(instance.m_index == m_materialUboIdx);
+			const U32 inputIdx = m_binaryMapping.m_uniformVars[instance.m_index].m_inputVarIdx;
+			const U32 arrayIdx = m_binaryMapping.m_uniformVars[instance.m_index].m_arrayIdx;
+			ShaderVariableBlockInfo& blockInfo = variant.m_blockInfos[inputIdx];
+
+			if(arrayIdx == 0)
+			{
+				blockInfo = instance.m_blockInfo;
+			}
+			else if(arrayIdx == 1)
+			{
+				ANKI_ASSERT(blockInfo.m_offset >= 0);
+				blockInfo.m_arraySize = max(blockInfo.m_arraySize, I16(arrayIdx + 1));
+				ANKI_ASSERT(instance.m_blockInfo.m_offset > blockInfo.m_offset);
+				blockInfo.m_arrayStride = instance.m_blockInfo.m_offset - blockInfo.m_offset;
+			}
+			else
+			{
+				ANKI_ASSERT(blockInfo.m_offset >= 0);
+				blockInfo.m_arraySize = max(blockInfo.m_arraySize, I16(arrayIdx + 1));
+			}
+
+			variant.m_activeInputVars.set(inputIdx);
+		}
+	}
+
+	// Init the opaques
+	variant.m_opaqueBindings.create(getAllocator(), m_inputVars.getSize(), -1);
+	for(const ShaderProgramBinaryOpaqueInstance& instance : binaryVariant->m_opaques)
+	{
+		const U32 opaqueIdx = instance.m_index;
+		const ShaderProgramBinaryOpaque& opaque = binary.m_opaques[opaqueIdx];
+		if(opaque.m_set != m_descriptorSet)
+		{
+			continue;
+		}
+
+		const U32 inputIdx = m_binaryMapping.m_opaques[opaqueIdx];
+		const Input& in = m_inputVars[inputIdx];
+		ANKI_ASSERT(in.isSampler() || in.isTexture());
+
+		variant.m_opaqueBindings[inputIdx] = I16(opaque.m_binding);
+		variant.m_activeInputVars.set(inputIdx);
+	}
+
+	// Set the constannt values
+	Array2d<ShaderSpecializationConstValue, U(ShaderType::COUNT), 64> constValues;
+	Array<U32, U(ShaderType::COUNT)> constValueCounts;
+	for(ShaderType shaderType : EnumIterable<ShaderType>())
+	{
+		if(!(shaderTypeToBit(shaderType) & m_shaderStages))
+		{
+			continue;
+		}
+
+		for(const ShaderProgramBinaryConstantInstance& instance : binaryVariant->m_constants)
+		{
+			const ShaderProgramBinaryConstant& c = binary.m_constants[instance.m_index];
+			if(!(c.m_shaderStages & shaderTypeToBit(shaderType)))
+			{
+				continue;
+			}
+
+			const U32 inputIdx = m_binaryMapping.m_constants[instance.m_index].m_inputVarIdx;
+			const U32 component = m_binaryMapping.m_constants[instance.m_index].m_component;
+
+			// Get value
+			const ShaderProgramResourceConstantValue2* value = nullptr;
+			for(U32 i = 0; i < info.m_constantValueCount; ++i)
+			{
+				if(info.m_constantValues[i].m_inputVariableIndex == inputIdx)
+				{
+					value = &info.m_constantValues[i];
+					break;
+				}
+			}
+			ANKI_ASSERT(value && "Forgot to set the value of a constant");
+
+			U32& count = constValueCounts[shaderType];
+			constValues[shaderType][count].m_constantId = c.m_constantId;
+			constValues[shaderType][count].m_dataType = c.m_type;
+			constValues[shaderType][count].m_int = value->m_ivec4[component];
+			++count;
+		}
+	}
+
+	// Create the program name
+	StringAuto progName(getTempAllocator());
+	getFilepathFilename(getFilename(), progName);
+	char* cprogName = const_cast<char*>(progName.cstr());
+	if(progName.getLength() > MAX_GR_OBJECT_NAME_LENGTH)
+	{
+		cprogName[MAX_GR_OBJECT_NAME_LENGTH] = '\0';
 	}
+
+	// Time to init the shaders
+	ShaderProgramInitInfo progInf(cprogName);
+	for(ShaderType shaderType : EnumIterable<ShaderType>())
+	{
+		if(!(shaderTypeToBit(shaderType) & m_shaderStages))
+		{
+			continue;
+		}
+
+		ShaderInitInfo inf(cprogName);
+		inf.m_shaderType = shaderType;
+		inf.m_binary = binary.m_codeBlocks[binaryVariant->m_codeBlockIndices[shaderType]].m_binary;
+		inf.m_constValues.setArray(&constValues[shaderType][0], constValueCounts[shaderType]);
+
+		progInf.m_shaders[shaderType] = getManager().getGrManager().newShader(inf);
+	}
+
+	// Create the program
+	variant.m_prog = getManager().getGrManager().newShaderProgram(progInf);
 }
 
 } // end namespace anki

+ 46 - 1
src/anki/resource/ShaderProgramResource2.h

@@ -74,16 +74,36 @@ public:
 		return m_prog;
 	}
 
-	/// Return true of the the variable is active.
+	/// Return true if the the variable is active in this variant.
 	Bool variableActive(const ShaderProgramResourceInputVariable2& var) const
 	{
 		return m_activeInputVars.get(var.m_index);
 	}
 
+	U32 getBinding(const ShaderProgramResourceInputVariable2& var) const
+	{
+		ANKI_ASSERT(m_opaqueBindings[var.m_index] >= 0);
+		return U32(m_opaqueBindings[var.m_index]);
+	}
+
+	U32 getUniformBlockSize() const
+	{
+		return m_uniBlockSize;
+	}
+
+	Bool usePushConstants() const
+	{
+		return m_usesPushConstants;
+	}
+
 private:
 	ShaderProgramPtr m_prog;
 
 	BitSet<128, U64> m_activeInputVars = {false};
+	DynamicArray<ShaderVariableBlockInfo> m_blockInfos;
+	DynamicArray<I16> m_opaqueBindings;
+	U32 m_uniBlockSize = 0;
+	Bool m_usesPushConstants = false;
 };
 
 /// Shader program resource. It loads special AnKi programs.
@@ -155,9 +175,34 @@ private:
 	DynamicArray<Input> m_inputVars;
 	DynamicArray<Mutator> m_mutators;
 
+	class UniformVarInfo
+	{
+	public:
+		U32 m_arrayIdx = 0;
+		U32 m_inputVarIdx = 0;
+	};
+
+	class ConstInfo
+	{
+	public:
+		U32 m_component = 0;
+		U32 m_inputVarIdx = 0;
+	};
+
+	class
+	{
+	public:
+		DynamicArray<UniformVarInfo> m_uniformVars;
+		DynamicArray<ConstInfo> m_constants;
+		DynamicArray<U32> m_opaques;
+	} m_binaryMapping;
+
 	mutable HashMap<U64, ShaderProgramResourceVariant2*> m_variants;
 	mutable RWMutex m_mtx;
 
+	U8 m_descriptorSet = MAX_U8;
+	U8 m_materialUboIdx = MAX_U8; ///< Index into the program binary.
+
 	ShaderTypeBit m_shaderStages = ShaderTypeBit::NONE;
 
 	void initVariant(const ShaderProgramResourceVariantInitInfo2& info, ShaderProgramResourceVariant2& variant) const;

+ 3 - 2
src/anki/shader_compiler/ShaderProgramBinary.h

@@ -246,7 +246,8 @@ public:
 class ShaderProgramBinaryVariant
 {
 public:
-	Array<U32, U32(ShaderType::COUNT)> m_codeBlockIndices = {}; ///< Index in ShaderProgramBinary::m_codeBlocks.
+	Array<U32, U32(ShaderType::COUNT)> m_codeBlockIndices =
+		{}; ///< Index in ShaderProgramBinary::m_codeBlocks. MAX_U32 means no shader.
 	WeakArray<ShaderProgramBinaryBlockInstance> m_uniformBlocks;
 	WeakArray<ShaderProgramBinaryBlockInstance> m_storageBlocks;
 	ShaderProgramBinaryBlockInstance* m_pushConstantBlock = nullptr;
@@ -312,7 +313,7 @@ public:
 class ShaderProgramBinaryCodeBlock
 {
 public:
-	WeakArray<U8, PtrSize> m_binary;
+	WeakArray<U8> m_binary;
 
 	template<typename TSerializer, typename TClass>
 	static void serializeCommon(TSerializer& s, TClass self)

+ 1 - 1
src/anki/shader_compiler/ShaderProgramBinary.xml

@@ -88,7 +88,7 @@
 
 		<class name="ShaderProgramBinaryCodeBlock" comment="Contains the IR (SPIR-V)">
 			<members>
-				<member name="m_binary" type="WeakArray&lt;U8, PtrSize&gt;" />
+				<member name="m_binary" type="WeakArray&lt;U8&gt;" />
 			</members>
 		</class>
 

+ 3 - 3
src/anki/shader_compiler/ShaderProgramCompiler.cpp

@@ -182,7 +182,7 @@ static Error compileVariant(ConstWeakArray<MutatorValue> mutation,
 	ANKI_CHECK(parser.generateVariant(mutation, parserVariant));
 
 	// Compile stages
-	Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirvBinaries;
+	Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirvBinaries;
 	for(ShaderType shaderType = ShaderType::FIRST; shaderType < ShaderType::COUNT; ++shaderType)
 	{
 		if(!(shaderTypeToBit(shaderType) & parser.getShaderTypes()))
@@ -217,7 +217,7 @@ static Error compileVariant(ConstWeakArray<MutatorValue> mutation,
 			memcpy(code, &spirv[0], spirv.getSizeInBytes());
 
 			ShaderProgramBinaryCodeBlock block;
-			block.m_binary.setArray(code, spirv.getSizeInBytes());
+			block.m_binary.setArray(code, U32(spirv.getSizeInBytes()));
 			codeBlocks.emplaceBack(block);
 
 			codeBlockHashes.emplaceBack(newHash);
@@ -532,7 +532,7 @@ static Error doReflection(
 
 	for(ShaderProgramBinaryVariant& variant : binary.m_variants)
 	{
-		Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirvs;
+		Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirvs;
 		for(ShaderType stage : EnumIterable<ShaderType>())
 		{
 			if(variant.m_codeBlockIndices[stage] != MAX_U32)

+ 11 - 11
src/anki/shader_compiler/ShaderProgramReflection.cpp

@@ -20,8 +20,7 @@ public:
 	{
 	}
 
-	ANKI_USE_RESULT static Error performSpirvReflection(
-		Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirv,
+	ANKI_USE_RESULT static Error performSpirvReflection(Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirv,
 		GenericMemoryPoolAllocator<U8> tmpAlloc,
 		ShaderReflectionVisitorInterface& interface);
 
@@ -98,7 +97,7 @@ private:
 	ANKI_USE_RESULT Error blockVariablesReflection(spirv_cross::TypeID resourceId, DynamicArrayAuto<Var>& vars) const;
 
 	ANKI_USE_RESULT Error blockVariableReflection(
-		const spirv_cross::SPIRType& type, CString parentVariable, DynamicArrayAuto<Var>& vars) const;
+		const spirv_cross::SPIRType& type, CString parentVariable, U32 baseOffset, DynamicArrayAuto<Var>& vars) const;
 };
 
 Error SpirvReflector::blockVariablesReflection(spirv_cross::TypeID resourceId, DynamicArrayAuto<Var>& vars) const
@@ -116,7 +115,7 @@ Error SpirvReflector::blockVariablesReflection(spirv_cross::TypeID resourceId, D
 			if(type.self == resourceId)
 			{
 				found = true;
-				err = blockVariableReflection(type, CString(), vars);
+				err = blockVariableReflection(type, CString(), 0, vars);
 			}
 		}
 	});
@@ -132,7 +131,7 @@ Error SpirvReflector::blockVariablesReflection(spirv_cross::TypeID resourceId, D
 }
 
 Error SpirvReflector::blockVariableReflection(
-	const spirv_cross::SPIRType& type, CString parentVariable, DynamicArrayAuto<Var>& vars) const
+	const spirv_cross::SPIRType& type, CString parentVariable, U32 baseOffset, DynamicArrayAuto<Var>& vars) const
 {
 	ANKI_ASSERT(type.basetype == spirv_cross::SPIRType::Struct);
 
@@ -167,7 +166,7 @@ Error SpirvReflector::blockVariableReflection(
 			ANKI_ASSERT(i < memb.size());
 			const spirv_cross::Meta::Decoration& dec = memb[i];
 			ANKI_ASSERT(dec.decoration_flags.get(spv::DecorationOffset));
-			var.m_blockInfo.m_offset = I16(dec.offset);
+			var.m_blockInfo.m_offset = I16(dec.offset + baseOffset);
 		}
 
 		// Array size
@@ -228,7 +227,7 @@ Error SpirvReflector::blockVariableReflection(
 		{
 			if(var.m_blockInfo.m_arraySize == 1)
 			{
-				ANKI_CHECK(blockVariableReflection(memberType, var.m_name, vars));
+				ANKI_CHECK(blockVariableReflection(memberType, var.m_name, var.m_blockInfo.m_offset, vars));
 			}
 			else
 			{
@@ -236,7 +235,8 @@ Error SpirvReflector::blockVariableReflection(
 				{
 					StringAuto newName(m_alloc);
 					newName.sprintf("%s[%u]", var.m_name.getBegin(), i);
-					ANKI_CHECK(blockVariableReflection(memberType, newName, vars));
+					ANKI_CHECK(blockVariableReflection(
+						memberType, newName, var.m_blockInfo.m_offset + var.m_blockInfo.m_arrayStride * i, vars));
 				}
 			}
 		}
@@ -288,7 +288,7 @@ Error SpirvReflector::blockVariableReflection(
 			return Error::FUNCTION_FAILED;
 		}
 
-		// Store the member
+		// Store the member if it's no struct
 		if(var.m_type != ShaderVariableDataType::NONE)
 		{
 			vars.emplaceBack(std::move(var));
@@ -576,7 +576,7 @@ Error SpirvReflector::constsReflection(DynamicArrayAuto<Const>& consts, ShaderTy
 	return Error::NONE;
 }
 
-Error SpirvReflector::performSpirvReflection(Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirv,
+Error SpirvReflector::performSpirvReflection(Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirv,
 	GenericMemoryPoolAllocator<U8> tmpAlloc,
 	ShaderReflectionVisitorInterface& interface)
 {
@@ -700,7 +700,7 @@ Error SpirvReflector::performSpirvReflection(Array<ConstWeakArray<U8, PtrSize>,
 	return Error::NONE;
 }
 
-Error performSpirvReflection(Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirv,
+Error performSpirvReflection(Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirv,
 	GenericMemoryPoolAllocator<U8> tmpAlloc,
 	ShaderReflectionVisitorInterface& interface)
 {

+ 1 - 1
src/anki/shader_compiler/ShaderProgramReflection.h

@@ -48,7 +48,7 @@ public:
 };
 
 /// Does reflection using SPIR-V.
-ANKI_USE_RESULT Error performSpirvReflection(Array<ConstWeakArray<U8, PtrSize>, U32(ShaderType::COUNT)> spirv,
+ANKI_USE_RESULT Error performSpirvReflection(Array<ConstWeakArray<U8>, U32(ShaderType::COUNT)> spirv,
 	GenericMemoryPoolAllocator<U8> tmpAlloc,
 	ShaderReflectionVisitorInterface& interface);
 /// @}

+ 8 - 1
tests/shader_compiler/ShaderProgramCompiler.cpp

@@ -9,7 +9,12 @@
 ANKI_TEST(ShaderCompiler, ShaderProgramCompilerSimple)
 {
 	const CString sourceCode = R"(
-#pragma anki mutator INSTANCE_COUNT 1 2 4 8 16 32 64
+#pragma anki mutator INSTANCE_COUNT 1 2 4
+
+struct Foo
+{
+	Mat4 m_mat;
+};
 
 struct Instanced
 {
@@ -17,10 +22,12 @@ struct Instanced
 	Mat3 m_ankiRotationMat;
 	Mat4 m_ankiModelViewMat;
 	Mat4 m_ankiPrevMvp;
+	Foo m_foo[2];
 };
 
 layout(set = 0, binding = 0) uniform ankiMaterial
 {
+	Vec4 u_whatever;
 	Instanced u_ankiPerInstance[INSTANCE_COUNT];
 	Vec4 u_color;
 };