瀏覽代碼

Bug fixes

Panagiotis Christopoulos Charitos 8 年之前
父節點
當前提交
6d3d0db28a

+ 3 - 2
programs/FsParticles.ankiprog

@@ -56,8 +56,9 @@ void main()
 	texCol.rgb = computeLightColor(texCol.rgb);
 	texCol.rgb = computeLightColor(texCol.rgb);
 #endif
 #endif
 	
 	
-	colorScale.a *= in_alpha;
-	particleAlpha(texCol, colorScale, colorBias);
+	vec4 colScale = colorScale;
+	colScale.a *= in_alpha;
+	particleAlpha(texCol, colScale, colorBias);
 }
 }
 			]]>
 			]]>
 			</source>
 			</source>

+ 2 - 2
shaders/ClusterLightCommon.glsl

@@ -95,7 +95,7 @@ layout(ANKI_UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING), std140, row_major) unifor
 		readFirstInvocationARB(u_lightingUniforms.prevViewProjMat[2]),                                                 \
 		readFirstInvocationARB(u_lightingUniforms.prevViewProjMat[2]),                                                 \
 		readFirstInvocationARB(u_lightingUniforms.prevViewProjMat[3]))
 		readFirstInvocationARB(u_lightingUniforms.prevViewProjMat[3]))
 
 
-#ifdef FRAGMENT_SHADER
+#ifdef ANKI_FRAGMENT_SHADER
 
 
 layout(ANKI_UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING + 1), std140) uniform u1_
 layout(ANKI_UBO_BINDING(LIGHT_SET, LIGHT_UBO_BINDING + 1), std140) uniform u1_
 {
 {
@@ -140,6 +140,6 @@ layout(ANKI_TEX_BINDING(LIGHT_SET, LIGHT_TEX_BINDING + 3)) uniform samplerCubeAr
 layout(ANKI_TEX_BINDING(LIGHT_SET, LIGHT_TEX_BINDING + 4)) uniform sampler2D u_integrationLut;
 layout(ANKI_TEX_BINDING(LIGHT_SET, LIGHT_TEX_BINDING + 4)) uniform sampler2D u_integrationLut;
 #endif
 #endif
 
 
-#endif // FRAGMENT_SHADER
+#endif // ANKI_FRAGMENT_SHADER
 
 
 #endif
 #endif

+ 1 - 1
shaders/FsCommonFrag.glsl

@@ -118,7 +118,7 @@ vec3 computeLightColor(vec3 diffCol)
 
 
 void particleAlpha(vec4 color, vec4 scaleColor, vec4 biasColor)
 void particleAlpha(vec4 color, vec4 scaleColor, vec4 biasColor)
 {
 {
-	writeGBuffer(color * mulColor + addColor);
+	writeGBuffer(color * scaleColor + biasColor);
 }
 }
 
 
 void fog(in sampler2D depthMap, in vec3 color, in float fogScale)
 void fog(in sampler2D depthMap, in vec3 color, in float fogScale)

+ 8 - 8
src/anki/gr/gl/ShaderImpl.cpp

@@ -38,11 +38,11 @@ static const char* SHADER_HEADER = R"(#version %u %s
 #define ANKI_IMAGE_BINDING(set_, binding_) binding = set_ * %u + binding_
 #define ANKI_IMAGE_BINDING(set_, binding_) binding = set_ * %u + binding_
 #define ANKI_TBO_BINDING(set_, binding_) binding = %u + set_ * %u + binding_
 #define ANKI_TBO_BINDING(set_, binding_) binding = %u + set_ * %u + binding_
 
 
-#if defined(FRAGMENT_SHADER)
+#if defined(ANKI_FRAGMENT_SHADER)
 #define ANKI_USING_FRAG_COORD(height_) vec4 anki_fragCoord = gl_FragCoord;
 #define ANKI_USING_FRAG_COORD(height_) vec4 anki_fragCoord = gl_FragCoord;
 #endif
 #endif
 
 
-#if defined(VERTEX_SHADER)
+#if defined(ANKI_VERTEX_SHADER)
 #define ANKI_WRITE_POSITION(x_) gl_Position = x_
 #define ANKI_WRITE_POSITION(x_) gl_Position = x_
 #endif
 #endif
 
 
@@ -70,12 +70,12 @@ Error ShaderImpl::init(ShaderType type, const CString& source)
 		GL_FRAGMENT_SHADER,
 		GL_FRAGMENT_SHADER,
 		GL_COMPUTE_SHADER}};
 		GL_COMPUTE_SHADER}};
 
 
-	static const Array<const char*, 6> shaderName = {{"VERTEX_SHADER",
-		"TESSELATION_CONTROL_SHADER",
-		"TESSELATION_EVALUATION_SHADER",
-		"GEOMETRY_SHADER",
-		"FRAGMENT_SHADER",
-		"COMPUTE_SHADER"}};
+	static const Array<const char*, 6> shaderName = {{"ANKI_VERTEX_SHADER",
+		"ANKI_TESSELATION_CONTROL_SHADER",
+		"ANKI_TESSELATION_EVALUATION_SHADER",
+		"ANKI_GEOMETRY_SHADER",
+		"ANKI_FRAGMENT_SHADER",
+		"ANKI_COMPUTE_SHADER"}};
 
 
 	m_type = type;
 	m_type = type;
 	m_glType = gltype[U(type)];
 	m_glType = gltype[U(type)];

+ 23 - 0
src/anki/gr/gl/ShaderProgramImpl.cpp

@@ -10,29 +10,51 @@
 namespace anki
 namespace anki
 {
 {
 
 
+static void deletePrograms(GLsizei n, const GLuint* progs)
+{
+	ANKI_ASSERT(n == 1);
+	ANKI_ASSERT(progs);
+	glDeleteProgram(*progs);
+}
+
+ShaderProgramImpl::ShaderProgramImpl(GrManager* manager)
+	: GlObject(manager)
+{
+}
+
+ShaderProgramImpl::~ShaderProgramImpl()
+{
+	destroyDeferred(deletePrograms);
+}
+
 Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
 Error ShaderProgramImpl::initGraphics(ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag)
 {
 {
 	m_glName = glCreateProgram();
 	m_glName = glCreateProgram();
 	ANKI_ASSERT(m_glName != 0);
 	ANKI_ASSERT(m_glName != 0);
 
 
 	glAttachShader(m_glName, vert->m_impl->getGlName());
 	glAttachShader(m_glName, vert->m_impl->getGlName());
+	m_shaders[ShaderType::VERTEX] = vert;
 
 
 	if(tessc)
 	if(tessc)
 	{
 	{
 		glAttachShader(m_glName, tessc->m_impl->getGlName());
 		glAttachShader(m_glName, tessc->m_impl->getGlName());
+		m_shaders[ShaderType::TESSELLATION_CONTROL] = tessc;
 	}
 	}
 
 
 	if(tesse)
 	if(tesse)
 	{
 	{
 		glAttachShader(m_glName, tesse->m_impl->getGlName());
 		glAttachShader(m_glName, tesse->m_impl->getGlName());
+		m_shaders[ShaderType::TESSELLATION_EVALUATION] = tesse;
 	}
 	}
 
 
 	if(geom)
 	if(geom)
 	{
 	{
 		glAttachShader(m_glName, geom->m_impl->getGlName());
 		glAttachShader(m_glName, geom->m_impl->getGlName());
+		m_shaders[ShaderType::GEOMETRY] = geom;
 	}
 	}
 
 
 	glAttachShader(m_glName, frag->m_impl->getGlName());
 	glAttachShader(m_glName, frag->m_impl->getGlName());
+	m_shaders[ShaderType::FRAGMENT] = frag;
 
 
 	return link(vert->m_impl->getGlName(), frag->m_impl->getGlName());
 	return link(vert->m_impl->getGlName(), frag->m_impl->getGlName());
 }
 }
@@ -43,6 +65,7 @@ Error ShaderProgramImpl::initCompute(ShaderPtr comp)
 	ANKI_ASSERT(m_glName != 0);
 	ANKI_ASSERT(m_glName != 0);
 
 
 	glAttachShader(m_glName, comp->m_impl->getGlName());
 	glAttachShader(m_glName, comp->m_impl->getGlName());
+	m_shaders[ShaderType::COMPUTE] = comp;
 
 
 	return link(0, 0);
 	return link(0, 0);
 }
 }

+ 4 - 15
src/anki/gr/gl/ShaderProgramImpl.h

@@ -13,32 +13,21 @@ namespace anki
 /// @addtogroup opengl
 /// @addtogroup opengl
 /// @{
 /// @{
 
 
-static inline void deletePrograms(GLsizei n, const GLuint* progs)
-{
-	ANKI_ASSERT(n == 1);
-	ANKI_ASSERT(progs);
-	glDeleteProgram(*progs);
-}
-
 /// Shader program implementation.
 /// Shader program implementation.
 class ShaderProgramImpl : public GlObject
 class ShaderProgramImpl : public GlObject
 {
 {
 public:
 public:
-	ShaderProgramImpl(GrManager* manager)
-		: GlObject(manager)
-	{
-	}
+	ShaderProgramImpl(GrManager* manager);
 
 
-	~ShaderProgramImpl()
-	{
-		destroyDeferred(deletePrograms);
-	}
+	~ShaderProgramImpl();
 
 
 	ANKI_USE_RESULT Error initGraphics(
 	ANKI_USE_RESULT Error initGraphics(
 		ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag);
 		ShaderPtr vert, ShaderPtr tessc, ShaderPtr tesse, ShaderPtr geom, ShaderPtr frag);
 	ANKI_USE_RESULT Error initCompute(ShaderPtr comp);
 	ANKI_USE_RESULT Error initCompute(ShaderPtr comp);
 
 
 private:
 private:
+	Array<ShaderPtr, U(ShaderType::COUNT)> m_shaders;
+
 	ANKI_USE_RESULT Error link(GLuint vert, GLuint frag);
 	ANKI_USE_RESULT Error link(GLuint vert, GLuint frag);
 };
 };
 /// @}
 /// @}

+ 8 - 8
src/anki/gr/vulkan/ShaderImpl.cpp

@@ -165,12 +165,12 @@ static const char* SHADER_HEADER = R"(#version 450 core
 #define ANKI_SS_BINDING(set_, binding_) set = set_, binding = %u + binding_
 #define ANKI_SS_BINDING(set_, binding_) set = set_, binding = %u + binding_
 #define ANKI_IMAGE_BINDING(set_, binding_) set = set_, binding = %u + binding_
 #define ANKI_IMAGE_BINDING(set_, binding_) set = set_, binding = %u + binding_
 
 
-#if defined(FRAGMENT_SHADER)
+#if defined(ANKI_FRAGMENT_SHADER)
 #define ANKI_USING_FRAG_COORD(h_) vec4 anki_fragCoord = \
 #define ANKI_USING_FRAG_COORD(h_) vec4 anki_fragCoord = \
 	vec4(gl_FragCoord.x, h_ - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w);
 	vec4(gl_FragCoord.x, h_ - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w);
 #endif
 #endif
 
 
-#if defined(VERTEX_SHADER)
+#if defined(ANKI_VERTEX_SHADER)
 #define ANKI_WRITE_POSITION(x_) gl_Position = x_; gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5
 #define ANKI_WRITE_POSITION(x_) gl_Position = x_; gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5
 #endif
 #endif
 
 
@@ -235,12 +235,12 @@ Error ShaderImpl::init(ShaderType shaderType, const CString& source)
 	auto alloc = getAllocator();
 	auto alloc = getAllocator();
 	StringAuto fullSrc(alloc);
 	StringAuto fullSrc(alloc);
 
 
-	static const Array<const char*, 6> shaderName = {{"VERTEX_SHADER",
-		"TESSELATION_CONTROL_SHADER",
-		"TESSELATION_EVALUATION_SHADER",
-		"GEOMETRY_SHADER",
-		"FRAGMENT_SHADER",
-		"COMPUTE_SHADER"}};
+	static const Array<const char*, 6> shaderName = {{"ANKI_VERTEX_SHADER",
+		"ANKI_TESSELATION_CONTROL_SHADER",
+		"ANKI_TESSELATION_EVALUATION_SHADER",
+		"ANKI_GEOMETRY_SHADER",
+		"ANKI_FRAGMENT_SHADER",
+		"ANKI_COMPUTE_SHADER"}};
 
 
 	fullSrc.sprintf(SHADER_HEADER,
 	fullSrc.sprintf(SHADER_HEADER,
 		&GPU_VENDOR_STR[getGrManagerImpl().getGpuVendor()][0],
 		&GPU_VENDOR_STR[getGrManagerImpl().getGpuVendor()][0],

+ 1 - 1
src/anki/resource/Material.cpp

@@ -439,7 +439,7 @@ const MaterialVariant& Material::getOrCreateVariant(const RenderingKey& key_) co
 	key.m_instanceCount = 1 << getInstanceGroupIdx(key.m_instanceCount);
 	key.m_instanceCount = 1 << getInstanceGroupIdx(key.m_instanceCount);
 
 
 	MaterialVariant& variant = m_variantMatrix[U(key.m_pass)][key.m_lod][getInstanceGroupIdx(key.m_instanceCount)];
 	MaterialVariant& variant = m_variantMatrix[U(key.m_pass)][key.m_lod][getInstanceGroupIdx(key.m_instanceCount)];
-	LockGuard<Mutex> lock(m_variantMatrixMtx);
+	LockGuard<SpinLock> lock(m_variantMatrixMtx);
 
 
 	if(variant.m_variant == nullptr)
 	if(variant.m_variant == nullptr)
 	{
 	{

+ 1 - 1
src/anki/resource/Material.h

@@ -239,7 +239,7 @@ private:
 
 
 	/// Matrix of variants.
 	/// Matrix of variants.
 	mutable Array3d<MaterialVariant, U(Pass::COUNT), MAX_LOD, MAX_INSTANCE_GROUPS> m_variantMatrix;
 	mutable Array3d<MaterialVariant, U(Pass::COUNT), MAX_LOD, MAX_INSTANCE_GROUPS> m_variantMatrix;
-	mutable Mutex m_variantMatrixMtx;
+	mutable SpinLock m_variantMatrixMtx;
 
 
 	DynamicArray<MaterialVariable> m_vars; ///< Non-const vars.
 	DynamicArray<MaterialVariable> m_vars; ///< Non-const vars.
 	DynamicArray<ShaderProgramResourceConstantValue> m_constValues;
 	DynamicArray<ShaderProgramResourceConstantValue> m_constValues;

+ 39 - 26
src/anki/resource/ShaderProgramResource.cpp

@@ -307,7 +307,6 @@ Error ShaderProgramResource::load(const ResourceFilename& filename)
 	StringListAuto constSrcList(getTempAllocator());
 	StringListAuto constSrcList(getTempAllocator());
 	ShaderTypeBit presentShaders = ShaderTypeBit::NONE;
 	ShaderTypeBit presentShaders = ShaderTypeBit::NONE;
 	Array<CString, 5> shaderSources;
 	Array<CString, 5> shaderSources;
-	const ShaderProgramResourceMutator* instanceMutator = nullptr;
 	ANKI_CHECK(shadersEl.getChildElement("shader", shaderEl));
 	ANKI_CHECK(shadersEl.getChildElement("shader", shaderEl));
 	do
 	do
 	{
 	{
@@ -337,7 +336,7 @@ Error ShaderProgramResource::load(const ResourceFilename& filename)
 
 
 		if(inputsEl)
 		if(inputsEl)
 		{
 		{
-			ANKI_CHECK(parseInputs(inputsEl, inputVarCount, constSrcList, instanceMutator));
+			ANKI_CHECK(parseInputs(inputsEl, inputVarCount, constSrcList));
 		}
 		}
 
 
 		// <source>
 		// <source>
@@ -348,10 +347,6 @@ Error ShaderProgramResource::load(const ResourceFilename& filename)
 		ANKI_CHECK(shaderEl.getNextSiblingElement("shader", shaderEl));
 		ANKI_CHECK(shaderEl.getNextSiblingElement("shader", shaderEl));
 	} while(shaderEl);
 	} while(shaderEl);
 
 
-#if ANKI_EXTRA_CHECKS
-	m_instancingMutator = instanceMutator;
-#endif
-
 	ANKI_ASSERT(inputVarCount == m_inputVars.getSize());
 	ANKI_ASSERT(inputVarCount == m_inputVars.getSize());
 
 
 	// Sanity checks
 	// Sanity checks
@@ -393,10 +388,7 @@ Error ShaderProgramResource::load(const ResourceFilename& filename)
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 
-Error ShaderProgramResource::parseInputs(XmlElement& inputsEl,
-	U& inputVarCount,
-	StringListAuto& constsSrc,
-	const ShaderProgramResourceMutator*& instanceMutator)
+Error ShaderProgramResource::parseInputs(XmlElement& inputsEl, U& inputVarCount, StringListAuto& constsSrc)
 {
 {
 	XmlElement inputEl;
 	XmlElement inputEl;
 	ANKI_CHECK(inputsEl.getChildElement("input", inputEl));
 	ANKI_CHECK(inputsEl.getChildElement("input", inputEl));
@@ -515,16 +507,15 @@ Error ShaderProgramResource::parseInputs(XmlElement& inputsEl,
 		ANKI_CHECK(inputEl.getAttributeTextOptional("instanceCount", instanceCountTxt, found));
 		ANKI_CHECK(inputEl.getAttributeTextOptional("instanceCount", instanceCountTxt, found));
 		if(found)
 		if(found)
 		{
 		{
-			m_instanced = true;
-
 			if(instanceCountTxt.isEmpty())
 			if(instanceCountTxt.isEmpty())
 			{
 			{
 				ANKI_RESOURCE_LOGE("instanceCount tag is empty for input variable %s", &name[0]);
 				ANKI_RESOURCE_LOGE("instanceCount tag is empty for input variable %s", &name[0]);
 				return ErrorCode::USER_DATA;
 				return ErrorCode::USER_DATA;
 			}
 			}
 
 
-			var.m_instancingMutator = tryFindMutator(instanceCountTxt);
-			if(!var.m_instancingMutator)
+			var.m_instanced = true;
+			const ShaderProgramResourceMutator* instancingMutator = tryFindMutator(instanceCountTxt);
+			if(!instancingMutator)
 			{
 			{
 				ANKI_RESOURCE_LOGE("Failed to find mutator %s, used as instanceCount attribute for input variable %s",
 				ANKI_RESOURCE_LOGE("Failed to find mutator %s, used as instanceCount attribute for input variable %s",
 					&instanceCountTxt[0],
 					&instanceCountTxt[0],
@@ -532,11 +523,11 @@ Error ShaderProgramResource::parseInputs(XmlElement& inputsEl,
 				return ErrorCode::USER_DATA;
 				return ErrorCode::USER_DATA;
 			}
 			}
 
 
-			if(!instanceMutator)
+			if(!m_instancingMutator)
 			{
 			{
-				instanceMutator = var.m_instancingMutator;
+				m_instancingMutator = instancingMutator;
 			}
 			}
-			else if(instanceMutator != var.m_instancingMutator)
+			else if(instancingMutator != m_instancingMutator)
 			{
 			{
 				ANKI_RESOURCE_LOGE("All input variables should have the same instancing mutator");
 				ANKI_RESOURCE_LOGE("All input variables should have the same instancing mutator");
 				return ErrorCode::USER_DATA;
 				return ErrorCode::USER_DATA;
@@ -706,12 +697,28 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 		memorySet<I16>(&variant.m_texUnits[0], -1, variant.m_texUnits.getSize());
 		memorySet<I16>(&variant.m_texUnits[0], -1, variant.m_texUnits.getSize());
 	}
 	}
 
 
+	// Get instance count, one mutation has it
+	U instanceCount = 1;
+	if(m_instancingMutator)
+	{
+		for(const ShaderProgramResourceMutation& m : mutations)
+		{
+			if(m.m_mutator == m_instancingMutator)
+			{
+				ANKI_ASSERT(m.m_value > 0);
+				instanceCount = m.m_value;
+				break;
+			}
+		}
+	}
+
 	// - Compute the block info for each var
 	// - Compute the block info for each var
 	// - Activate vars
 	// - Activate vars
 	// - Compute varius strings
 	// - Compute varius strings
 	StringListAuto blockCode(getTempAllocator());
 	StringListAuto blockCode(getTempAllocator());
 	StringListAuto constsCode(getTempAllocator());
 	StringListAuto constsCode(getTempAllocator());
 	StringListAuto texturesCode(getTempAllocator());
 	StringListAuto texturesCode(getTempAllocator());
+	StringListAuto globalsCode(getTempAllocator());
 	U texUnit = 0;
 	U texUnit = 0;
 
 
 	for(const ShaderProgramResourceInputVariable& in : m_inputVars)
 	for(const ShaderProgramResourceInputVariable& in : m_inputVars)
@@ -721,7 +728,6 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 			continue;
 			continue;
 		}
 		}
 
 
-		U instanceCount = 1;
 		variant.m_activeInputVars.set(in.m_idx);
 		variant.m_activeInputVars.set(in.m_idx);
 
 
 		// Init block info
 		// Init block info
@@ -731,7 +737,7 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 
 
 			// std140 rules
 			// std140 rules
 			blockInfo.m_offset = variant.m_uniBlockSize;
 			blockInfo.m_offset = variant.m_uniBlockSize;
-			blockInfo.m_arraySize = instanceCount;
+			blockInfo.m_arraySize = (in.m_instanced) ? instanceCount : 1;
 
 
 			if(in.m_dataType == ShaderVariableDataType::FLOAT)
 			if(in.m_dataType == ShaderVariableDataType::FLOAT)
 			{
 			{
@@ -802,19 +808,19 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 				ANKI_ASSERT(0);
 				ANKI_ASSERT(0);
 			}
 			}
 
 
-			if(instanceCount > 1)
+			if(in.m_instanced && instanceCount > 1)
 			{
 			{
-				blockCode.pushBackSprintf(R"(%s %s_i[%s];
-#if VERTEX_SHADER
-#	define %s s%_i[gl_InstanceID]
+				blockCode.pushBackSprintf(
+					"%s %s_i[%s];\n", &toString(in.m_dataType)[0], &in.m_name[0], &m_instancingMutator->getName()[0]);
+
+				globalsCode.pushBackSprintf(R"(#if defined(ANKI_VERTEX_SHADER)
+%s %s = %s_i[gl_InstanceID];
 #else
 #else
 // TODO
 // TODO
 #endif
 #endif
 )",
 )",
 					&toString(in.m_dataType)[0],
 					&toString(in.m_dataType)[0],
 					&in.m_name[0],
 					&in.m_name[0],
-					&in.m_instancingMutator->getName()[0],
-					&in.m_name[0],
 					&in.m_name[0]);
 					&in.m_name[0]);
 			}
 			}
 			else
 			else
@@ -899,7 +905,7 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 		StringAuto str(getTempAllocator());
 		StringAuto str(getTempAllocator());
 		blockCode.join("", str);
 		blockCode.join("", str);
 
 
-		shaderHeaderSrc.pushBack("layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform u0_ {\n");
+		shaderHeaderSrc.pushBack("layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform sprubo00_ {\n");
 		shaderHeaderSrc.pushBack(str.toCString());
 		shaderHeaderSrc.pushBack(str.toCString());
 		shaderHeaderSrc.pushBack("};\n");
 		shaderHeaderSrc.pushBack("};\n");
 	}
 	}
@@ -911,6 +917,13 @@ void ShaderProgramResource::initVariant(WeakArray<const ShaderProgramResourceMut
 		shaderHeaderSrc.pushBack(str.toCString());
 		shaderHeaderSrc.pushBack(str.toCString());
 	}
 	}
 
 
+	if(globalsCode)
+	{
+		StringAuto str(getTempAllocator());
+		globalsCode.join("", str);
+		shaderHeaderSrc.pushBack(str.toCString());
+	}
+
 	StringAuto shaderHeader(getTempAllocator());
 	StringAuto shaderHeader(getTempAllocator());
 	shaderHeaderSrc.join("", shaderHeader);
 	shaderHeaderSrc.join("", shaderHeader);
 
 

+ 5 - 12
src/anki/resource/ShaderProgramResource.h

@@ -91,7 +91,7 @@ public:
 
 
 	Bool isInstanced() const
 	Bool isInstanced() const
 	{
 	{
-		return m_instancingMutator != nullptr;
+		return m_instanced;
 	}
 	}
 
 
 	Bool isConstant() const
 	Bool isConstant() const
@@ -121,11 +121,11 @@ private:
 	};
 	};
 
 
 	String m_name;
 	String m_name;
+	DynamicArray<Mutator> m_mutators;
 	U32 m_idx;
 	U32 m_idx;
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
 	ShaderVariableDataType m_dataType = ShaderVariableDataType::NONE;
 	Bool8 m_const = false;
 	Bool8 m_const = false;
-	const ShaderProgramResourceMutator* m_instancingMutator = nullptr;
-	DynamicArray<Mutator> m_mutators;
+	Bool8 m_instanced = false;
 
 
 	Bool isTexture() const
 	Bool isTexture() const
 	{
 	{
@@ -347,7 +347,7 @@ public:
 
 
 	Bool isInstanced() const
 	Bool isInstanced() const
 	{
 	{
-		return m_instanced;
+		return m_instancingMutator != nullptr;
 	}
 	}
 
 
 private:
 private:
@@ -360,17 +360,10 @@ private:
 	mutable Mutex m_mtx;
 	mutable Mutex m_mtx;
 
 
 	Bool8 m_tessellation = false;
 	Bool8 m_tessellation = false;
-	Bool8 m_instanced = false;
-
-#if ANKI_EXTRA_CHECKS
 	const ShaderProgramResourceMutator* m_instancingMutator = nullptr;
 	const ShaderProgramResourceMutator* m_instancingMutator = nullptr;
-#endif
 
 
 	/// Parse whatever is inside <inputs>
 	/// Parse whatever is inside <inputs>
-	ANKI_USE_RESULT Error parseInputs(XmlElement& inputsEl,
-		U& inputVarCount,
-		StringListAuto& constsSrc,
-		const ShaderProgramResourceMutator*& instanceMutator);
+	ANKI_USE_RESULT Error parseInputs(XmlElement& inputsEl, U& inputVarCount, StringListAuto& constsSrc);
 
 
 	U64 computeVariantHash(WeakArray<const ShaderProgramResourceMutation> mutations,
 	U64 computeVariantHash(WeakArray<const ShaderProgramResourceMutation> mutations,
 		WeakArray<const ShaderProgramResourceConstantValue> constants) const;
 		WeakArray<const ShaderProgramResourceConstantValue> constants) const;