Ver código fonte

Work on the compiler

Panagiotis Christopoulos Charitos 6 anos atrás
pai
commit
62d495affb

+ 1 - 0
src/anki/shader_compiler/Common.h

@@ -15,6 +15,7 @@ namespace anki
 /// @{
 
 constexpr U32 MAX_SHADER_PROGRAM_INPUT_VARIABLES = 128;
+constexpr U32 MAX_SHADER_BINARY_NAME_LENGTH = 63;
 
 #define ANKI_SHADER_COMPILER_LOGI(...) ANKI_LOG(" SHC", NORMAL, __VA_ARGS__)
 #define ANKI_SHADER_COMPILER_LOGE(...) ANKI_LOG(" SHC", ERROR, __VA_ARGS__)

+ 10 - 8
src/anki/shader_compiler/ShaderProgramBinary.h

@@ -18,8 +18,7 @@ namespace anki
 class ShaderProgramBinaryInput
 {
 public:
-	char* m_name;
-	U32 m_nameSize; ///< It includes the '\0' char.
+	Array<char, MAX_SHADER_BINARY_NAME_LENGTH + 1> m_name;
 	U32 m_firstSpecializationConstantIndex; ///< It's MAX_U32 if it's not a constant.
 	Bool m_instanced;
 	ShaderVariableDataType m_dataType;
@@ -27,13 +26,13 @@ public:
 	template<typename TSerializer, typename TClass>
 	static void serializeCommon(TSerializer& s, TClass self)
 	{
-		s.doValue("m_nameSize", offsetof(ShaderProgramBinaryInput, m_nameSize), self.m_nameSize);
+		s.doArray(
+			"m_name", offsetof(ShaderProgramBinaryInput, m_name), &self.m_name[0], MAX_SHADER_BINARY_NAME_LENGTH + 1);
 		s.doValue("m_firstSpecializationConstantIndex",
 			offsetof(ShaderProgramBinaryInput, m_firstSpecializationConstantIndex),
 			self.m_firstSpecializationConstantIndex);
 		s.doValue("m_instanced", offsetof(ShaderProgramBinaryInput, m_instanced), self.m_instanced);
 		s.doValue("m_dataType", offsetof(ShaderProgramBinaryInput, m_dataType), self.m_dataType);
-		s.doDynamicArray("m_name", offsetof(ShaderProgramBinaryInput, m_name), self.m_name, self.m_nameSize);
 	}
 
 	template<typename TDeserializer>
@@ -53,19 +52,18 @@ public:
 class ShaderProgramBinaryMutator
 {
 public:
-	char* m_name;
+	Array<char, MAX_SHADER_BINARY_NAME_LENGTH + 1> m_name;
 	I32* m_values;
-	U32 m_nameSize;
 	U32 m_valueCount;
 	Bool m_instanceCount;
 
 	template<typename TSerializer, typename TClass>
 	static void serializeCommon(TSerializer& s, TClass self)
 	{
-		s.doValue("m_nameSize", offsetof(ShaderProgramBinaryMutator, m_nameSize), self.m_nameSize);
+		s.doArray(
+			"m_name", offsetof(ShaderProgramBinaryMutator, m_name), &self.m_name[0], MAX_SHADER_BINARY_NAME_LENGTH + 1);
 		s.doValue("m_valueCount", offsetof(ShaderProgramBinaryMutator, m_valueCount), self.m_valueCount);
 		s.doValue("m_instanceCount", offsetof(ShaderProgramBinaryMutator, m_instanceCount), self.m_instanceCount);
-		s.doDynamicArray("m_name", offsetof(ShaderProgramBinaryMutator, m_name), self.m_name, self.m_nameSize);
 		s.doDynamicArray("m_values", offsetof(ShaderProgramBinaryMutator, m_values), self.m_values, self.m_valueCount);
 	}
 
@@ -175,9 +173,11 @@ public:
 	ShaderProgramBinaryMutator* m_mutators;
 	ShaderProgramBinaryInput* m_inputVariables;
 	ShaderProgramBinaryCode* m_codeBlocks;
+	ShaderProgramBinaryVariant* m_variants;
 	U32 m_mutatorCount;
 	U32 m_inputVariableCount;
 	U32 m_codeBlockCount;
+	U32 m_variantCount;
 	U32 m_descriptorSet;
 	ShaderTypeBit m_presentShaderTypes;
 
@@ -189,6 +189,7 @@ public:
 		s.doValue(
 			"m_inputVariableCount", offsetof(ShaderProgramBinary, m_inputVariableCount), self.m_inputVariableCount);
 		s.doValue("m_codeBlockCount", offsetof(ShaderProgramBinary, m_codeBlockCount), self.m_codeBlockCount);
+		s.doValue("m_variantCount", offsetof(ShaderProgramBinary, m_variantCount), self.m_variantCount);
 		s.doValue("m_descriptorSet", offsetof(ShaderProgramBinary, m_descriptorSet), self.m_descriptorSet);
 		s.doValue(
 			"m_presentShaderTypes", offsetof(ShaderProgramBinary, m_presentShaderTypes), self.m_presentShaderTypes);
@@ -199,6 +200,7 @@ public:
 			self.m_inputVariableCount);
 		s.doDynamicArray(
 			"m_codeBlocks", offsetof(ShaderProgramBinary, m_codeBlocks), self.m_codeBlocks, self.m_codeBlockCount);
+		s.doDynamicArray("m_variants", offsetof(ShaderProgramBinary, m_variants), self.m_variants, self.m_variantCount);
 	}
 
 	template<typename TDeserializer>

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

@@ -8,8 +8,7 @@
 	<classes>
 		<class name="ShaderProgramBinaryInput" comment="Shader program input variable">
 			<members>
-				<member name="m_name" type="char" pointer="true" array_size="m_nameSize" />
-				<member name="m_nameSize" type="U32" comment="It includes the '\0' char" />
+				<member name="m_name" type="char" array_size="MAX_SHADER_BINARY_NAME_LENGTH + 1" />
 				<member name="m_firstSpecializationConstantIndex" type="U32" comment="It's MAX_U32 if it's not a constant" />
 				<member name="m_instanced" type="Bool" />
 				<member name="m_dataType" type="ShaderVariableDataType" />
@@ -18,9 +17,8 @@
 
 		<class name="ShaderProgramBinaryMutator" comment="Shader program mutator">
 			<members>
-				<member name="m_name" type="char" pointer="true" array_size="m_nameSize" />
+				<member name="m_name" type="char" array_size="MAX_SHADER_BINARY_NAME_LENGTH + 1" />
 				<member name="m_values" type="I32" pointer="true" array_size="m_valueCount" />
-				<member name="m_nameSize" type="U32" />
 				<member name="m_valueCount" type="U32" />
 				<member name="m_instanceCount" type="Bool" />
 			</members>
@@ -53,9 +51,11 @@
 				<member name="m_mutators" type="ShaderProgramBinaryMutator" pointer="true" array_size="m_mutatorCount" />
 				<member name="m_inputVariables" type="ShaderProgramBinaryInput" pointer="true" array_size="m_inputVariableCount" />
 				<member name="m_codeBlocks" type="ShaderProgramBinaryCode" pointer="true" array_size="m_codeBlockCount" />
+				<member name="m_variants" type="ShaderProgramBinaryVariant" pointer="true" array_size="m_variantCount" />
 				<member name="m_mutatorCount" type="U32" />
 				<member name="m_inputVariableCount" type="U32" />
 				<member name="m_codeBlockCount" type="U32" />
+				<member name="m_variantCount" type="U32" />
 				<member name="m_descriptorSet" type="U32" />
 				<member name="m_presentShaderTypes" type="ShaderTypeBit" />
 			</members>

+ 2 - 2
src/anki/shader_compiler/ShaderProgramBinaryExtra.h

@@ -28,7 +28,7 @@ public:
 	template<typename TSerializer>
 	void operator()(const ShaderVariableBlockInfo& x, TSerializer& serializer)
 	{
-		serializeShaderVariableBlockInfo<TSerializer, ShaderVariableBlockInfo&>(x, serializer);
+		serializeShaderVariableBlockInfo<TSerializer, const ShaderVariableBlockInfo&>(x, serializer);
 	}
 };
 
@@ -40,7 +40,7 @@ public:
 	template<typename TDeserializer>
 	void operator()(ShaderVariableBlockInfo& x, TDeserializer& deserialize)
 	{
-		serializeShaderVariableBlockInfo<TDeserializer, const ShaderVariableBlockInfo&>(x, deserialize);
+		serializeShaderVariableBlockInfo<TDeserializer, ShaderVariableBlockInfo&>(x, deserialize);
 	}
 };
 

+ 215 - 106
src/anki/shader_compiler/ShaderProgramCompiler.cpp

@@ -11,12 +11,7 @@
 namespace anki
 {
 
-/// XXX
-static Bool spinDials(DynamicArrayAuto<U32> dials, ConstWeakArray<ShaderProgramParserMutator> mutators)
-{
-	// XXX
-	return false;
-}
+static const char* SHADER_BINARY_MAGIC = "ANKISHB1";
 
 Error ShaderProgramBinaryWrapper::serializeToFile(CString fname) const
 {
@@ -46,24 +41,207 @@ Error ShaderProgramBinaryWrapper::deserializeFromFile(CString fname)
 	return Error::NONE;
 }
 
+/// XXX
+static Bool spinDials(DynamicArrayAuto<U32> dials, ConstWeakArray<ShaderProgramParserMutator> mutators)
+{
+	// XXX
+	return false;
+}
+
+static Error compileVariant(ConstWeakArray<ShaderProgramParserMutatorState> mutatorStates,
+	const ShaderProgramParser& parser,
+	ShaderProgramBinaryVariant& variant,
+	DynamicArrayAuto<ShaderProgramBinaryCode>& codeBlocks,
+	DynamicArrayAuto<U64>& codeBlockHashes,
+	GenericMemoryPoolAllocator<U8> tmpAlloc,
+	GenericMemoryPoolAllocator<U8> binaryAlloc)
+{
+	variant = {};
+
+	// Generate the source and the rest for the variant
+	ShaderProgramParserVariant parserVariant;
+	ANKI_CHECK(parser.generateVariant(mutatorStates, parserVariant));
+
+	// Active vars
+	{
+		BitSet<MAX_SHADER_PROGRAM_INPUT_VARIABLES, U64> active(false);
+		for(PtrSize i = 0; i < parser.getInputs().getSize(); ++i)
+		{
+			if(parserVariant.isInputActive(parser.getInputs()[i]))
+			{
+				active.set(i, true);
+			}
+		}
+		variant.m_activeVariables = active.getData();
+	}
+
+	// Compile stages
+	for(ShaderType shaderType = ShaderType::FIRST; shaderType < ShaderType::COUNT; ++shaderType)
+	{
+		if(!(shaderTypeToBit(shaderType) & parser.getShaderStages()))
+		{
+			variant.m_binaryIndices[shaderType] = MAX_U32;
+			continue;
+		}
+
+		// Compile
+		DynamicArrayAuto<U8> spirv(tmpAlloc);
+		ANKI_CHECK(compilerGlslToSpirv(parserVariant.getSource(shaderType), shaderType, tmpAlloc, spirv));
+		ANKI_ASSERT(spirv.getSize() > 0);
+
+		// Check if the spirv is already generated
+		const U64 newHash = computeHash(&spirv[0], spirv.getSize());
+		Bool found = false;
+		for(PtrSize i = 0; i < codeBlockHashes.getSize(); ++i)
+		{
+			if(codeBlockHashes[i] == newHash)
+			{
+				// Found it
+				variant.m_binaryIndices[shaderType] = U32(i);
+				found = true;
+				break;
+			}
+		}
+
+		// Create it if not found
+		if(!found)
+		{
+			U8* code = binaryAlloc.allocate(spirv.getSizeInBytes());
+			memcpy(code, &spirv[0], spirv.getSizeInBytes());
+
+			ShaderProgramBinaryCode block;
+			block.m_binary = code;
+			block.m_binarySize = spirv.getSizeInBytes();
+			codeBlocks.emplaceBack(block);
+
+			codeBlockHashes.emplaceBack(newHash);
+
+			variant.m_binaryIndices[shaderType] = U32(codeBlocks.getSize() - 1);
+		}
+	}
+
+	// Mutator values
+	variant.m_mutatorValues = binaryAlloc.newArray<I32>(parser.getMutators().getSize());
+	for(PtrSize i = 0; i < parser.getMutators().getSize(); ++i)
+	{
+		variant.m_mutatorValues[i] = mutatorStates[i].m_value;
+	}
+
+	// Input vars
+	{
+		ShaderVariableBlockInfo defaultInfo;
+		defaultInfo.m_arraySize = -1;
+		defaultInfo.m_arrayStride = -1;
+		defaultInfo.m_matrixStride = -1;
+		defaultInfo.m_offset = -1;
+		variant.m_blockInfos = binaryAlloc.newArray<ShaderVariableBlockInfo>(parser.getInputs().getSize(), defaultInfo);
+
+		variant.m_bindings = binaryAlloc.newArray<I16>(parser.getInputs().getSize(), -1);
+
+		for(PtrSize i = 0; i < parser.getInputs().getSize(); ++i)
+		{
+			const ShaderProgramParserInput& parserInput = parser.getInputs()[i];
+			if(!parserVariant.isInputActive(parserInput))
+			{
+				continue;
+			}
+
+			if(parserInput.inUbo())
+			{
+				variant.m_blockInfos[i] = parserVariant.getBlockInfo(parserInput);
+			}
+
+			if(parserInput.isSampler() || parserInput.isTexture())
+			{
+				variant.m_bindings[i] = I16(parserVariant.getBinding(parserInput));
+			}
+		}
+	}
+
+	// Misc
+	variant.m_mutatorValueCount = U32(parser.getMutators().getSize());
+	variant.m_inputVariableCount = U32(parser.getInputs().getSize());
+	variant.m_blockSize = parserVariant.getBlockSize();
+	variant.m_usesPushConstants = parserVariant.usesPushConstants();
+
+	return Error::NONE;
+}
+
 Error ShaderProgramCompiler::compile(CString fname,
-	ShaderProgramFilesystemInterface* fsystem,
+	ShaderProgramFilesystemInterface& fsystem,
 	GenericMemoryPoolAllocator<U8> tempAllocator,
 	U32 pushConstantsSize,
 	U32 backendMinor,
 	U32 backendMajor,
 	GpuVendor gpuVendor,
-	ShaderProgramBinaryWrapper& binary)
+	ShaderProgramBinaryWrapper& binaryW) const
 {
-	ANKI_ASSERT(fsystem);
-
-	binary.cleanup();
-	GenericMemoryPoolAllocator<U8> binaryAllocator;
+	// Initialize the binary
+	binaryW.cleanup();
+	binaryW.m_singleAllocation = false;
+	GenericMemoryPoolAllocator<U8> binaryAllocator = binaryW.m_alloc;
+	binaryW.m_binary = binaryAllocator.newInstance<ShaderProgramBinary>();
+	ShaderProgramBinary& binary = *binaryW.m_binary;
+	binary = {};
+	memcpy(&binary.m_magic[0], SHADER_BINARY_MAGIC, 8);
 
 	// Parse source
-	ShaderProgramParser parser(fname, fsystem, tempAllocator, pushConstantsSize, backendMinor, backendMajor, gpuVendor);
+	ShaderProgramParser parser(
+		fname, &fsystem, tempAllocator, pushConstantsSize, backendMinor, backendMajor, gpuVendor);
 	ANKI_CHECK(parser.parse());
 
+	// Inputs
+	if(parser.getInputs().getSize() > 0)
+	{
+		binary.m_inputVariableCount = U32(parser.getInputs().getSize());
+		binary.m_inputVariables = binaryAllocator.newArray<ShaderProgramBinaryInput>(binary.m_inputVariableCount);
+
+		for(U32 i = 0; i < binary.m_inputVariableCount; ++i)
+		{
+			ShaderProgramBinaryInput& out = binary.m_inputVariables[i];
+			const ShaderProgramParserInput& in = parser.getInputs()[i];
+
+			ANKI_ASSERT(in.getName().getLength() < out.m_name.getSize());
+			memcpy(&out.m_name[0], in.getName().cstr(), in.getName().getLength() + 1);
+
+			out.m_firstSpecializationConstantIndex = MAX_U32;
+			in.isConstant(&out.m_firstSpecializationConstantIndex);
+
+			out.m_instanced = in.isInstanced();
+			out.m_dataType = in.getDataType();
+		}
+	}
+	else
+	{
+		ANKI_ASSERT(binary.m_inputVariableCount == 0 && binary.m_inputVariables == nullptr);
+	}
+
+	// Mutators
+	if(parser.getMutators().getSize() > 0)
+	{
+		binary.m_mutatorCount = U32(parser.getMutators().getSize());
+		binary.m_mutators = binaryAllocator.newArray<ShaderProgramBinaryMutator>(binary.m_mutatorCount);
+
+		for(U32 i = 0; i < binary.m_mutatorCount; ++i)
+		{
+			ShaderProgramBinaryMutator& out = binary.m_mutators[i];
+			const ShaderProgramParserMutator& in = parser.getMutators()[i];
+
+			ANKI_ASSERT(in.getName().getLength() < out.m_name.getSize());
+			memcpy(&out.m_name[0], in.getName().cstr(), in.getName().getLength() + 1);
+
+			out.m_valueCount = U32(in.getValues().getSize());
+			out.m_values = binaryAllocator.newArray<I32>(out.m_valueCount);
+			memcpy(out.m_values, &in.getValues()[0], in.getValues().getSizeInBytes());
+
+			out.m_instanceCount = in.isInstanceCount();
+		}
+	}
+	else
+	{
+		ANKI_ASSERT(binary.m_mutatorCount == 0 && binary.m_mutators == nullptr);
+	}
+
 	// Create all variants
 	if(parser.getMutators().getSize() > 0)
 	{
@@ -84,107 +262,38 @@ Error ShaderProgramCompiler::compile(CString fname,
 		// Spin for all possible combinations of mutators and
 		// - Create the spirv
 		// - Populate the binary variant
-		ShaderProgramParserVariant parserVariant;
 		do
 		{
 			ShaderProgramBinaryVariant& variant = *variants.emplaceBack();
-			variant = {};
-
-			// Generate the source and the rest for the variant
-			ANKI_CHECK(parser.generateVariant(states, parserVariant));
-
-			// Compile
-			for(ShaderType shaderType = ShaderType::FIRST; shaderType < ShaderType::COUNT; ++shaderType)
-			{
-				if(!(shaderTypeToBit(shaderType) & parser.getShaderStages()))
-				{
-					continue;
-				}
-
-				// Compile
-				DynamicArrayAuto<U8> spirv(tempAllocator);
-				ANKI_CHECK(compilerGlslToSpirv(parserVariant.getSource(shaderType), shaderType, tempAllocator, spirv));
-				ANKI_ASSERT(spirv.getSize() > 0);
-
-				// Check if the spirv is already generated
-				const U64 hash = computeHash(&spirv[0], spirv.getSize());
-				Bool found = false;
-				for(PtrSize i = 0; i < codeBlockHashes.getSize(); ++i)
-				{
-					if(codeBlockHashes[i] == hash)
-					{
-						// Found it
-						variant.m_binaryIndices[shaderType] = U32(i);
-						found = true;
-						break;
-					}
-				}
-
-				// Create it if not found
-				if(!found)
-				{
-					U8* code = binaryAllocator.allocate(spirv.getSizeInBytes());
-					memcpy(code, &spirv[0], spirv.getSizeInBytes());
-
-					ShaderProgramBinaryCode block;
-					block.m_binary = code;
-					block.m_binarySize = spirv.getSizeInBytes();
-					codeBlocks.emplaceBack(block);
-
-					codeBlockHashes.emplaceBack(hash);
-
-					variant.m_binaryIndices[shaderType] = U32(codeBlocks.getSize() - 1);
-				}
-			}
-
-			// Active vars
-			BitSet<MAX_SHADER_PROGRAM_INPUT_VARIABLES, U64> active(false);
-			for(PtrSize i = 0; i < parser.getInputs().getSize(); ++i)
-			{
-				if(parserVariant.isInputActive(parser.getInputs()[i]))
-				{
-					active.set(i, true);
-				}
-			}
-			variant.m_activeVariables = active.getData();
-
-			// Mutator values
-			variant.m_mutatorValues = binaryAllocator.newArray<I32>(parser.getMutators().getSize());
-			for(PtrSize i = 0; i < parser.getMutators().getSize(); ++i)
-			{
-				variant.m_mutatorValues[i] = states[i].m_value;
-			}
-
-			// Input vars
-			ShaderVariableBlockInfo defaultInfo;
-			defaultInfo.m_arraySize = -1;
-			defaultInfo.m_arrayStride = -1;
-			defaultInfo.m_matrixStride = -1;
-			defaultInfo.m_offset = -1;
-			variant.m_blockInfos =
-				binaryAllocator.newArray<ShaderVariableBlockInfo>(parser.getInputs().getSize(), defaultInfo);
-
-			variant.m_bindings = binaryAllocator.newArray<I16>(parser.getInputs().getSize(), -1);
+			ANKI_CHECK(
+				compileVariant(states, parser, variant, codeBlocks, codeBlockHashes, tempAllocator, binaryAllocator));
+		} while(spinDials(dials, parser.getMutators()));
 
-			for(U32 i = 0; i < parser.getInputs().getSize(); ++i)
-			{
-				const ShaderProgramParserInput& parserInput = parser.getInputs()[i];
-				if(!parserVariant.isInputActive(parserInput))
-				{
-					continue;
-				}
-
-				if(parserInput.inUbo())
-				{
-					variant.m_blockInfos[i] = parserVariant.getBlockInfo(parserInput);
-				}
-			}
+		// Store to binary
+		binary.m_variantCount = U32(variants.getSizeInBytes());
+		PtrSize size, storage;
+		variants.moveAndReset(binary.m_variants, size, storage);
 
-		} while(spinDials(dials, parser.getMutators()));
+		binary.m_codeBlockCount = U32(codeBlocks.getSize());
+		codeBlocks.moveAndReset(binary.m_codeBlocks, size, storage);
 	}
 	else
 	{
-		// TODO
+		DynamicArrayAuto<ShaderProgramParserMutatorState> states(tempAllocator);
+		DynamicArrayAuto<ShaderProgramBinaryCode> codeBlocks(binaryAllocator);
+		DynamicArrayAuto<U64> codeBlockHashes(tempAllocator);
+
+		binary.m_variantCount = 1;
+		binary.m_variants = binaryAllocator.newInstance<ShaderProgramBinaryVariant>();
+		binary.m_variants = {};
+
+		ANKI_CHECK(compileVariant(
+			states, parser, binary.m_variants[0], codeBlocks, codeBlockHashes, tempAllocator, binaryAllocator));
+		ANKI_ASSERT(codeBlocks.getSize() == 1);
+
+		binary.m_codeBlockCount = 1;
+		PtrSize size, storage;
+		codeBlocks.moveAndReset(binary.m_codeBlocks, size, storage);
 	}
 
 	return Error::NONE;

+ 2 - 2
src/anki/shader_compiler/ShaderProgramCompiler.h

@@ -49,13 +49,13 @@ class ShaderProgramCompiler : public NonCopyable
 {
 public:
 	ANKI_USE_RESULT Error compile(CString fname,
-		ShaderProgramFilesystemInterface* fsystem,
+		ShaderProgramFilesystemInterface& fsystem,
 		GenericMemoryPoolAllocator<U8> tempAllocator,
 		U32 pushConstantsSize,
 		U32 backendMinor,
 		U32 backendMajor,
 		GpuVendor gpuVendor,
-		ShaderProgramBinaryWrapper& binary);
+		ShaderProgramBinaryWrapper& binary) const;
 };
 /// @}
 

+ 11 - 1
src/anki/shader_compiler/ShaderProgramParser.cpp

@@ -426,7 +426,7 @@ Error ShaderProgramParser::parsePragmaInput(const StringAuto* begin, const Strin
 		}
 
 		// Check if there are duplicates
-		for(U i = 0; i < m_inputs.getSize() - 1; ++i)
+		for(PtrSize i = 0; i < m_inputs.getSize() - 1; ++i)
 		{
 			if(m_inputs[i].m_name == *begin)
 			{
@@ -434,6 +434,11 @@ Error ShaderProgramParser::parsePragmaInput(const StringAuto* begin, const Strin
 			}
 		}
 
+		if(begin->getLength() > MAX_SHADER_BINARY_NAME_LENGTH)
+		{
+			ANKI_PP_ERROR_MALFORMED_MSG("Too big name");
+		}
+
 		input.m_name.create(begin->toCString());
 		++begin;
 	}
@@ -639,6 +644,11 @@ Error ShaderProgramParser::parsePragmaMutator(
 			}
 		}
 
+		if(begin->getLength() > MAX_SHADER_BINARY_NAME_LENGTH)
+		{
+			ANKI_PP_ERROR_MALFORMED_MSG("Too big name");
+		}
+
 		mutator.m_name.create(begin->toCString());
 		++begin;
 	}

+ 16 - 0
src/anki/shader_compiler/ShaderProgramParser.h

@@ -150,6 +150,22 @@ public:
 		return m_blockInfos[in.m_idx];
 	}
 
+	U32 getBinding(const ShaderProgramParserInput& in) const
+	{
+		ANKI_ASSERT(in.isSampler() && in.isTexture() && m_bindings[in.m_idx] >= 0);
+		return U32(m_bindings[in.m_idx]);
+	}
+
+	U32 getBlockSize() const
+	{
+		return m_uniBlockSize;
+	}
+
+	Bool usesPushConstants() const
+	{
+		return m_usesPushConstants;
+	}
+
 private:
 	GenericMemoryPoolAllocator<U8> m_alloc;
 	Array<String, U(ShaderType::COUNT)> m_sources;

+ 1 - 1
src/anki/util/Serializer.h

@@ -145,7 +145,7 @@ private:
 	template<typename T>
 	static void checkStruct()
 	{
-		static_assert(std::is_pod<T>::value, "Only PODs are supported in this serializer");
+		static_assert(!std::is_polymorphic<T>::value, "Only PODs are supported in this serializer");
 		static_assert(alignof(T) <= ANKI_SAFE_ALIGNMENT, "Alignments can't exceed ANKI_SAFE_ALIGNMENT");
 	}
 };