Pārlūkot izejas kodu

Move the global resources of forward shading to set 0. This fixes a bug in Vulkan

Panagiotis Christopoulos Charitos 8 gadi atpakaļ
vecāks
revīzija
0533f57d11

+ 1 - 0
.travis.yml

@@ -27,6 +27,7 @@ addons:
       - g++-6
       - g++-6
       - clang-3.7
       - clang-3.7
       - libvulkan-dev
       - libvulkan-dev
+      - libegl1-mesa-dev
 
 
 script:
 script:
   - mkdir build 
   - mkdir build 

+ 7 - 2
programs/ForwardShadingFog.ankiprog

@@ -5,10 +5,13 @@ Code licensed under the BSD License.
 http://www.anki3d.org/LICENSE
 http://www.anki3d.org/LICENSE
 -->
 -->
 <shaderProgram>
 <shaderProgram>
+	<descriptorSet index="1"/>
+
 	<shaders>
 	<shaders>
 		<shader type="vert">
 		<shader type="vert">
 			<inputs>
 			<inputs>
 				<input name="mvp" type="mat4"/>
 				<input name="mvp" type="mat4"/>
+				<input name="modelView" type="mat4"/>
 			</inputs>
 			</inputs>
 
 
 			<source><![CDATA[
 			<source><![CDATA[
@@ -17,6 +20,7 @@ http://www.anki3d.org/LICENSE
 void main() 
 void main() 
 {
 {
 	ANKI_WRITE_POSITION(mvp * vec4(in_position, 1.0));
 	ANKI_WRITE_POSITION(mvp * vec4(in_position, 1.0));
+	out_posViewSpace = (modelView * vec4(in_position, 1.0)).xyz;
 }
 }
 			]]></source>
 			]]></source>
 		</shader>
 		</shader>
@@ -24,7 +28,8 @@ void main()
 		<shader type="frag">
 		<shader type="frag">
 			<inputs>
 			<inputs>
 				<input name="fogColor" type="vec3" const="1"/>
 				<input name="fogColor" type="vec3" const="1"/>
-				<input name="fogScale" type="float" const="1"/>
+				<input name="fogAlphaScale" type="float" const="1"/>
+				<input name="fogDistanceOfMaxThikness" type="float" const="1"/>
 			</inputs>
 			</inputs>
 
 
 			<source><![CDATA[
 			<source><![CDATA[
@@ -32,7 +37,7 @@ void main()
 
 
 void main() 
 void main() 
 {
 {
-	fog(fogColor, fogScale);
+	fog(fogColor, fogAlphaScale, fogDistanceOfMaxThikness);
 }
 }
 			]]></source>
 			]]></source>
 		</shader>
 		</shader>

+ 2 - 0
programs/ForwardShadingParticles.ankiprog

@@ -5,6 +5,8 @@ Code licensed under the BSD License.
 http://www.anki3d.org/LICENSE
 http://www.anki3d.org/LICENSE
 -->
 -->
 <shaderProgram>
 <shaderProgram>
+	<descriptorSet index="1"/>
+
 	<mutators>
 	<mutators>
 		<mutator name="ANIMATED_TEXTURE" values="0 1"/>
 		<mutator name="ANIMATED_TEXTURE" values="0 1"/>
 		<mutator name="LIGHT" values="0 1"/>
 		<mutator name="LIGHT" values="0 1"/>

+ 11 - 17
shaders/ForwardShadingCommonFrag.glsl

@@ -12,8 +12,8 @@
 #include "shaders/Clusterer.glsl"
 #include "shaders/Clusterer.glsl"
 
 
 // Global resources
 // Global resources
-layout(ANKI_TEX_BINDING(1, 0)) uniform sampler2D anki_msDepthRt;
-#define LIGHT_SET 1
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D anki_msDepthRt;
+#define LIGHT_SET 0
 #define LIGHT_UBO_BINDING 0
 #define LIGHT_UBO_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_TEX_BINDING 1
 #define LIGHT_TEX_BINDING 1
@@ -123,29 +123,23 @@ void particleAlpha(vec4 color, vec4 scaleColor, vec4 biasColor)
 	writeGBuffer(color * scaleColor + biasColor);
 	writeGBuffer(color * scaleColor + biasColor);
 }
 }
 
 
-void fog(vec3 color, float fogScale)
+void fog(vec3 color, float fogAlphaScale, float fogDistanceOfMaxThikness)
 {
 {
 	const vec2 screenSize = 1.0 / RENDERER_SIZE;
 	const vec2 screenSize = 1.0 / RENDERER_SIZE;
 
 
 	vec2 texCoords = gl_FragCoord.xy * screenSize;
 	vec2 texCoords = gl_FragCoord.xy * screenSize;
 	float depth = texture(anki_msDepthRt, texCoords).r;
 	float depth = texture(anki_msDepthRt, texCoords).r;
-	float diff;
+	float zFeatherFactor;
 
 
-	if(depth < 1.0)
-	{
-		float zNear = u_near;
-		float zFar = u_far;
-		vec2 linearDepths = (2.0 * zNear) / (zFar + zNear - vec2(depth, gl_FragCoord.z) * (zFar - zNear));
+	vec4 fragPosVspace4 = u_invProjMat * vec4(UV_TO_NDC(vec3(texCoords, depth)), 1.0);
+	float sceneZVspace = fragPosVspace4.z / fragPosVspace4.w;
 
 
-		diff = linearDepths.x - linearDepths.y;
-	}
-	else
-	{
-		// The depth buffer is cleared at this place. Set the diff to zero to avoid weird pop ups
-		diff = 0.0;
-	}
+	float diff = max(0.0, in_posViewSpace.z - sceneZVspace);
+
+	zFeatherFactor = min(1.0, diff / fogDistanceOfMaxThikness);
 
 
-	writeGBuffer(vec4(color, diff * fogScale));
+	writeGBuffer(vec4(color, zFeatherFactor * fogAlphaScale));
+	// writeGBuffer(vec4(vec3(zFeatherFactor), 1.0));
 }
 }
 
 
 #endif
 #endif

+ 1 - 1
shaders/ForwardShadingCommonVert.glsl

@@ -10,7 +10,7 @@
 #include "shaders/Common.glsl"
 #include "shaders/Common.glsl"
 
 
 // Global resources
 // Global resources
-#define LIGHT_SET 1
+#define LIGHT_SET 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_SS_BINDING 0
 #define LIGHT_TEX_BINDING 1
 #define LIGHT_TEX_BINDING 1
 #define LIGHT_UBO_BINDING 0
 #define LIGHT_UBO_BINDING 0

+ 9 - 10
src/anki/renderer/ForwardShading.cpp

@@ -130,18 +130,17 @@ void ForwardShading::buildCommandBuffers(RenderingContext& ctx, U threadId, U th
 	CommandBufferPtr cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 	CommandBufferPtr cmdb = m_r->getGrManager().newInstance<CommandBuffer>(cinf);
 	ctx.m_forwardShading.m_commandBuffers[threadId] = cmdb;
 	ctx.m_forwardShading.m_commandBuffers[threadId] = cmdb;
 
 
-	cmdb->informTextureCurrentUsage(m_r->getDepthDownscale().m_hd.m_depthRt,
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ);
+	cmdb->informTextureCurrentUsage(m_r->getDepthDownscale().m_qd.m_depthRt, TextureUsageBit::SAMPLED_FRAGMENT);
 	cmdb->informTextureCurrentUsage(m_rt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
 	cmdb->informTextureCurrentUsage(m_rt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE);
 
 
-	cmdb->bindTexture(1, 0, m_r->getDepthDownscale().m_hd.m_depthRt);
-	cmdb->bindTexture(1, 1, m_r->getShadowMapping().m_spotTexArray);
-	cmdb->bindTexture(1, 2, m_r->getShadowMapping().m_omniTexArray);
-	bindUniforms(cmdb, 1, 0, ctx.m_lightShading.m_commonToken);
-	bindUniforms(cmdb, 1, 1, ctx.m_lightShading.m_pointLightsToken);
-	bindUniforms(cmdb, 1, 2, ctx.m_lightShading.m_spotLightsToken);
-	bindStorage(cmdb, 1, 0, ctx.m_lightShading.m_clustersToken);
-	bindStorage(cmdb, 1, 1, ctx.m_lightShading.m_lightIndicesToken);
+	cmdb->bindTexture(0, 0, m_r->getDepthDownscale().m_qd.m_depthRt);
+	cmdb->bindTexture(0, 1, m_r->getShadowMapping().m_spotTexArray);
+	cmdb->bindTexture(0, 2, m_r->getShadowMapping().m_omniTexArray);
+	bindUniforms(cmdb, 0, 0, ctx.m_lightShading.m_commonToken);
+	bindUniforms(cmdb, 0, 1, ctx.m_lightShading.m_pointLightsToken);
+	bindUniforms(cmdb, 0, 2, ctx.m_lightShading.m_spotLightsToken);
+	bindStorage(cmdb, 0, 0, ctx.m_lightShading.m_clustersToken);
+	bindStorage(cmdb, 0, 1, ctx.m_lightShading.m_lightIndicesToken);
 
 
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setViewport(0, 0, m_width, m_height);
 	cmdb->setBlendFactors(
 	cmdb->setBlendFactors(

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

@@ -61,6 +61,7 @@ Error Material::load(const ResourceFilename& filename)
 	CString fname;
 	CString fname;
 	ANKI_CHECK(rootEl.getAttributeText("shaderProgram", fname));
 	ANKI_CHECK(rootEl.getAttributeText("shaderProgram", fname));
 	ANKI_CHECK(getManager().loadResource(fname, m_prog));
 	ANKI_CHECK(getManager().loadResource(fname, m_prog));
+	m_descriptorSetIdx = m_prog->getDescriptorSetIndex();
 
 
 	// shadow
 	// shadow
 	ANKI_CHECK(rootEl.getAttributeNumberOptional("shadow", m_shadow, present));
 	ANKI_CHECK(rootEl.getAttributeNumberOptional("shadow", m_shadow, present));

+ 11 - 0
src/anki/resource/Material.h

@@ -240,12 +240,23 @@ public:
 		return m_vars;
 		return m_vars;
 	}
 	}
 
 
+	ShaderProgramResourcePtr getShaderProgramResource() const
+	{
+		return m_prog;
+	}
+
+	U getDescriptorSetIndex() const
+	{
+		return m_descriptorSetIdx;
+	}
+
 private:
 private:
 	ShaderProgramResourcePtr m_prog;
 	ShaderProgramResourcePtr m_prog;
 
 
 	Bool8 m_shadow = true;
 	Bool8 m_shadow = true;
 	Bool8 m_forwardShading = false;
 	Bool8 m_forwardShading = false;
 	U8 m_lodCount = 1;
 	U8 m_lodCount = 1;
+	U8 m_descriptorSetIdx = 0; ///< Cache the value from the m_prog;
 
 
 	const ShaderProgramResourceMutator* m_lodMutator = nullptr;
 	const ShaderProgramResourceMutator* m_lodMutator = nullptr;
 	const ShaderProgramResourceMutator* m_passMutator = nullptr;
 	const ShaderProgramResourceMutator* m_passMutator = nullptr;

+ 24 - 3
src/anki/resource/ShaderProgramResource.cpp

@@ -196,6 +196,23 @@ Error ShaderProgramResource::load(const ResourceFilename& filename)
 	XmlElement rootEl;
 	XmlElement rootEl;
 	ANKI_CHECK(doc.getChildElement("shaderProgram", rootEl));
 	ANKI_CHECK(doc.getChildElement("shaderProgram", rootEl));
 
 
+	// <descriptorSet>
+	XmlElement dsetEl;
+	ANKI_CHECK(rootEl.getChildElementOptional("descriptorSet", dsetEl));
+	if(dsetEl)
+	{
+		ANKI_CHECK(dsetEl.getAttributeNumber("index", m_descriptorSet));
+		if(m_descriptorSet >= MAX_DESCRIPTOR_SETS)
+		{
+			ANKI_RESOURCE_LOGE("<descriptorSet> should be lower than %u", U(MAX_DESCRIPTOR_SETS - 1));
+			return ErrorCode::USER_DATA;
+		}
+	}
+	else
+	{
+		m_descriptorSet = 0;
+	}
+
 	// <mutators>
 	// <mutators>
 	XmlElement mutatorsEl;
 	XmlElement mutatorsEl;
 	ANKI_CHECK(rootEl.getChildElementOptional("mutators", mutatorsEl));
 	ANKI_CHECK(rootEl.getChildElementOptional("mutators", mutatorsEl));
@@ -667,7 +684,8 @@ Error ShaderProgramResource::parseInputs(XmlElement& inputsEl,
 		{
 		{
 			if(blockSrc.isEmpty())
 			if(blockSrc.isEmpty())
 			{
 			{
-				blockSrc.pushBack("layout(ANKI_UBO_BINDING(0, 0), std140, row_major) uniform sprubo00_ {\n");
+				blockSrc.pushBackSprintf(
+					"layout(ANKI_UBO_BINDING(%u, 0), std140, row_major) uniform sprubo00_ {\n", U(m_descriptorSet));
 			}
 			}
 
 
 			blockSrc.pushBackSprintf("#if %s_DEFINED == 1\n", &name[0]);
 			blockSrc.pushBackSprintf("#if %s_DEFINED == 1\n", &name[0]);
@@ -699,8 +717,11 @@ Error ShaderProgramResource::parseInputs(XmlElement& inputsEl,
 		if(var.isTexture())
 		if(var.isTexture())
 		{
 		{
 			globalsSrc.pushBackSprintf("#if %s_DEFINED == 1\n", &name[0]);
 			globalsSrc.pushBackSprintf("#if %s_DEFINED == 1\n", &name[0]);
-			globalsSrc.pushBackSprintf(
-				"layout(ANKI_TEX_BINDING(0, %s_TEXUNIT)) uniform %s %s;\n", &name[0], &typeTxt[0], &name[0]);
+			globalsSrc.pushBackSprintf("layout(ANKI_TEX_BINDING(%u, %s_TEXUNIT)) uniform %s %s;\n",
+				U(m_descriptorSet),
+				&name[0],
+				&typeTxt[0],
+				&name[0]);
 			globalsSrc.pushBack("#endif\n");
 			globalsSrc.pushBack("#endif\n");
 		}
 		}
 
 

+ 17 - 0
src/anki/resource/ShaderProgramResource.h

@@ -274,6 +274,8 @@ static_assert(sizeof(ShaderProgramResourceConstantValue) == sizeof(Vec4) * 2, "N
 /// XML file format:
 /// XML file format:
 /// @code
 /// @code
 /// <shaderProgram>
 /// <shaderProgram>
+///		[<descriptorSet index="0 | 1"/>] (4)
+///
 /// 	[<mutators> (1)
 /// 	[<mutators> (1)
 /// 		<mutator name="str" values="array of ints" [instanced="0 | 1"]/>
 /// 		<mutator name="str" values="array of ints" [instanced="0 | 1"]/>
 /// 	</mutators>]
 /// 	</mutators>]
@@ -310,6 +312,7 @@ static_assert(sizeof(ShaderProgramResourceConstantValue) == sizeof(Vec4) * 2, "N
 /// (2): This lists a subset of mutators and out of these variants a subset of their values. The input variable will
 /// (2): This lists a subset of mutators and out of these variants a subset of their values. The input variable will
 ///      become active only on those mutators. Mutators not listed are implicitly added with all their values.
 ///      become active only on those mutators. Mutators not listed are implicitly added with all their values.
 /// (3): Global inputs. For all shaders.
 /// (3): Global inputs. For all shaders.
+/// (4): By default it's 0 but you can change the set resources are bound in the shader.
 class ShaderProgramResource : public ResourceObject
 class ShaderProgramResource : public ResourceObject
 {
 {
 public:
 public:
@@ -320,11 +323,13 @@ public:
 	/// Load the resource.
 	/// Load the resource.
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename);
 	ANKI_USE_RESULT Error load(const ResourceFilename& filename);
 
 
+	/// Get the array of input variables.
 	const DynamicArray<ShaderProgramResourceInputVariable>& getInputVariables() const
 	const DynamicArray<ShaderProgramResourceInputVariable>& getInputVariables() const
 	{
 	{
 		return m_inputVars;
 		return m_inputVars;
 	}
 	}
 
 
+	/// Try to find an input variable.
 	const ShaderProgramResourceInputVariable* tryFindInputVariable(CString name) const
 	const ShaderProgramResourceInputVariable* tryFindInputVariable(CString name) const
 	{
 	{
 		for(const ShaderProgramResourceInputVariable& m : m_inputVars)
 		for(const ShaderProgramResourceInputVariable& m : m_inputVars)
@@ -337,11 +342,13 @@ public:
 		return nullptr;
 		return nullptr;
 	}
 	}
 
 
+	/// Get the array of mutators.
 	const DynamicArray<ShaderProgramResourceMutator>& getMutators() const
 	const DynamicArray<ShaderProgramResourceMutator>& getMutators() const
 	{
 	{
 		return m_mutators;
 		return m_mutators;
 	}
 	}
 
 
+	/// Try to find a mutator.
 	const ShaderProgramResourceMutator* tryFindMutator(CString name) const
 	const ShaderProgramResourceMutator* tryFindMutator(CString name) const
 	{
 	{
 		for(const ShaderProgramResourceMutator& m : m_mutators)
 		for(const ShaderProgramResourceMutator& m : m_mutators)
@@ -385,21 +392,30 @@ public:
 			variant);
 			variant);
 	}
 	}
 
 
+	/// Has tessellation shaders.
 	Bool hasTessellation() const
 	Bool hasTessellation() const
 	{
 	{
 		return m_tessellation;
 		return m_tessellation;
 	}
 	}
 
 
+	/// Return true if it's instanced.
 	Bool isInstanced() const
 	Bool isInstanced() const
 	{
 	{
 		return m_instancingMutator != nullptr;
 		return m_instancingMutator != nullptr;
 	}
 	}
 
 
+	/// Get the mutator that controls the instancing.
 	const ShaderProgramResourceMutator* getInstancingMutator() const
 	const ShaderProgramResourceMutator* getInstancingMutator() const
 	{
 	{
 		return m_instancingMutator;
 		return m_instancingMutator;
 	}
 	}
 
 
+	/// The value of attribute "index" in <descriptorSet> tag.
+	U getDescriptorSetIndex() const
+	{
+		return m_descriptorSet;
+	}
+
 private:
 private:
 	DynamicArray<ShaderProgramResourceInputVariable> m_inputVars;
 	DynamicArray<ShaderProgramResourceInputVariable> m_inputVars;
 	DynamicArray<ShaderProgramResourceMutator> m_mutators;
 	DynamicArray<ShaderProgramResourceMutator> m_mutators;
@@ -411,6 +427,7 @@ private:
 
 
 	Bool8 m_tessellation = false;
 	Bool8 m_tessellation = false;
 	Bool8 m_compute = false;
 	Bool8 m_compute = false;
+	U8 m_descriptorSet = 0;
 	const ShaderProgramResourceMutator* m_instancingMutator = nullptr;
 	const ShaderProgramResourceMutator* m_instancingMutator = nullptr;
 
 
 	/// Parse whatever is inside <inputs>
 	/// Parse whatever is inside <inputs>

+ 8 - 7
src/anki/scene/ModelNode.cpp

@@ -109,10 +109,11 @@ void ModelPatchNode::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const v
 		trfs[i] = Mat4(self2.getParent()->getComponentAt<MoveComponent>(0).getWorldTransform());
 		trfs[i] = Mat4(self2.getParent()->getComponentAt<MoveComponent>(0).getWorldTransform());
 	}
 	}
 
 
-	StagingGpuMemoryToken token;
 	self.getComponentAt<RenderComponent>(1).allocateAndSetupUniforms(
 	self.getComponentAt<RenderComponent>(1).allocateAndSetupUniforms(
-		ctx, WeakArray<const Mat4>(&trfs[0], userData.getSize()), *ctx.m_stagingGpuAllocator, token);
-	cmdb->bindUniformBuffer(0, 0, token.m_buffer, token.m_offset, token.m_range);
+		self.m_modelPatch->getMaterial()->getDescriptorSetIndex(),
+		ctx,
+		WeakArray<const Mat4>(&trfs[0], userData.getSize()),
+		*ctx.m_stagingGpuAllocator);
 
 
 	// Draw
 	// Draw
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
@@ -285,10 +286,10 @@ void ModelNode::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const void*>
 		trfs[i] = Mat4(self2.getComponentAt<MoveComponent>(0).getWorldTransform());
 		trfs[i] = Mat4(self2.getComponentAt<MoveComponent>(0).getWorldTransform());
 	}
 	}
 
 
-	StagingGpuMemoryToken token;
-	self.getComponentAt<RenderComponent>(3).allocateAndSetupUniforms(
-		ctx, WeakArray<const Mat4>(&trfs[0], userData.getSize()), *ctx.m_stagingGpuAllocator, token);
-	cmdb->bindUniformBuffer(0, 0, token.m_buffer, token.m_offset, token.m_range);
+	self.getComponentAt<RenderComponent>(3).allocateAndSetupUniforms(patch->getMaterial()->getDescriptorSetIndex(),
+		ctx,
+		WeakArray<const Mat4>(&trfs[0], userData.getSize()),
+		*ctx.m_stagingGpuAllocator);
 
 
 	// Draw
 	// Draw
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,
 	cmdb->drawElements(PrimitiveTopology::TRIANGLES,

+ 2 - 3
src/anki/scene/ParticleEmitter.cpp

@@ -290,9 +290,8 @@ void ParticleEmitter::drawCallback(RenderQueueDrawContext& ctx, WeakArray<const
 
 
 	// Uniforms
 	// Uniforms
 	Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
 	Array<Mat4, 1> trf = {{Mat4::getIdentity()}};
-	StagingGpuMemoryToken token;
-	self.getComponent<RenderComponent>().allocateAndSetupUniforms(ctx, trf, *ctx.m_stagingGpuAllocator, token);
-	cmdb->bindUniformBuffer(0, 0, token.m_buffer, token.m_offset, token.m_range);
+	self.getComponent<RenderComponent>().allocateAndSetupUniforms(
+		self.m_particleEmitterResource->getMaterial()->getDescriptorSetIndex(), ctx, trf, *ctx.m_stagingGpuAllocator);
 
 
 	// Draw
 	// Draw
 	cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);
 	cmdb->drawArrays(PrimitiveTopology::TRIANGLE_STRIP, 4, self.m_aliveParticlesCount, 0, 0);

+ 6 - 5
src/anki/scene/RenderComponent.cpp

@@ -30,10 +30,8 @@ RenderComponent::~RenderComponent()
 	m_vars.destroy(getAllocator());
 	m_vars.destroy(getAllocator());
 }
 }
 
 
-void RenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
-	WeakArray<const Mat4> transforms,
-	StagingGpuMemoryManager& alloc,
-	StagingGpuMemoryToken& token) const
+void RenderComponent::allocateAndSetupUniforms(
+	U set, const RenderQueueDrawContext& ctx, WeakArray<const Mat4> transforms, StagingGpuMemoryManager& alloc) const
 {
 {
 	ANKI_ASSERT(transforms.getSize() <= MAX_INSTANCES);
 	ANKI_ASSERT(transforms.getSize() <= MAX_INSTANCES);
 
 
@@ -41,6 +39,7 @@ void RenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx
 	const ShaderProgramResourceVariant& progVariant = variant.getShaderProgramResourceVariant();
 	const ShaderProgramResourceVariant& progVariant = variant.getShaderProgramResourceVariant();
 
 
 	// Allocate uniform memory
 	// Allocate uniform memory
+	StagingGpuMemoryToken token;
 	U8* uniforms =
 	U8* uniforms =
 		static_cast<U8*>(alloc.allocateFrame(variant.getUniformBlockSize(), StagingGpuMemoryType::UNIFORM, token));
 		static_cast<U8*>(alloc.allocateFrame(variant.getUniformBlockSize(), StagingGpuMemoryType::UNIFORM, token));
 	void* const uniformsBegin = uniforms;
 	void* const uniformsBegin = uniforms;
@@ -187,13 +186,15 @@ void RenderComponent::allocateAndSetupUniforms(const RenderQueueDrawContext& ctx
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		case ShaderVariableDataType::SAMPLER_CUBE:
 		{
 		{
 			ctx.m_commandBuffer->bindTexture(
 			ctx.m_commandBuffer->bindTexture(
-				0, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
+				set, progVariant.getTextureUnit(progvar), mvar.getValue<TextureResourcePtr>()->getGrTexture());
 			break;
 			break;
 		}
 		}
 		default:
 		default:
 			ANKI_ASSERT(0);
 			ANKI_ASSERT(0);
 		} // end switch
 		} // end switch
 	}
 	}
+
+	ctx.m_commandBuffer->bindUniformBuffer(set, 0, token.m_buffer, token.m_offset, token.m_range);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 3 - 3
src/anki/scene/RenderComponent.h

@@ -100,10 +100,10 @@ public:
 		return err;
 		return err;
 	}
 	}
 
 
-	void allocateAndSetupUniforms(const RenderQueueDrawContext& ctx,
+	void allocateAndSetupUniforms(U set,
+		const RenderQueueDrawContext& ctx,
 		WeakArray<const Mat4> transforms,
 		WeakArray<const Mat4> transforms,
-		StagingGpuMemoryManager& alloc,
-		StagingGpuMemoryToken& token) const;
+		StagingGpuMemoryManager& alloc) const;
 
 
 	virtual void setupRenderableQueueElement(RenderableQueueElement& el) const = 0;
 	virtual void setupRenderableQueueElement(RenderableQueueElement& el) const = 0;