Browse Source

Add ray tracing support in shader programs

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
452500d402

+ 109 - 20
src/anki/gr/ShaderProgram.h

@@ -14,43 +14,132 @@ namespace anki
 /// @addtogroup graphics
 /// @{
 
+/// @memberof RayTracingShaders
+class RayTracingHitGroup
+{
+public:
+	ShaderPtr m_closestHitShader;
+	ShaderPtr m_anyHitShader;
+};
+
+/// @memberof ShaderProgramInitInfo
+class RayTracingShaders
+{
+public:
+	ShaderPtr m_rayGenShader;
+	ShaderPtr m_missShader;
+	WeakArray<RayTracingHitGroup> m_hitGroups;
+};
+
 /// ShaderProgram init info.
 class ShaderProgramInitInfo : public GrBaseInitInfo
 {
 public:
-	Array<ShaderPtr, U32(ShaderType::COUNT)> m_shaders = {};
+	/// Option 1
+	Array<ShaderPtr, U32(ShaderType::LAST_GRAPHICS + 1)> m_graphicsShaders;
 
-	ShaderProgramInitInfo(CString name = {})
-		: GrBaseInitInfo(name)
-	{
-	}
+	/// Option 2
+	ShaderPtr m_computeShader;
 
-	ShaderProgramInitInfo(const ShaderPtr& compute, CString name = {})
-		: GrBaseInitInfo(name)
-	{
-		m_shaders[compute->getShaderType()] = compute;
-	}
+	/// Option 3
+	RayTracingShaders m_rayTracingShaders;
 
-	ShaderProgramInitInfo(const ShaderPtr& vert, const ShaderPtr& frag, CString name = {})
+	ShaderProgramInitInfo(CString name = {})
 		: GrBaseInitInfo(name)
 	{
-		m_shaders[vert->getShaderType()] = vert;
-		m_shaders[frag->getShaderType()] = frag;
 	}
 
 	Bool isValid() const
 	{
-		ShaderTypeBit mask = ShaderTypeBit::NONE;
-		for(ShaderType i : EnumIterable<ShaderType>())
+		ShaderTypeBit graphicsMask = ShaderTypeBit::NONE;
+		for(ShaderType i = ShaderType::FIRST_GRAPHICS; i <= ShaderType::LAST_GRAPHICS; ++i)
+		{
+			if(m_graphicsShaders[i])
+			{
+				if(m_graphicsShaders[i]->getShaderType() != i)
+				{
+					return false;
+				}
+				graphicsMask |= ShaderTypeBit(1 << i);
+			}
+		}
+
+		if(!!graphicsMask
+		   && (graphicsMask & (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
+				  != (ShaderTypeBit::VERTEX | ShaderTypeBit::FRAGMENT))
+		{
+			return false;
+		}
+
+		Bool compute = false;
+		if(m_computeShader)
+		{
+			if(m_computeShader->getShaderType() != ShaderType::COMPUTE)
+			{
+				return false;
+			}
+			compute = true;
+		}
+
+		if(compute && !!graphicsMask)
+		{
+			return false;
+		}
+
+		ShaderTypeBit rtMask = ShaderTypeBit::NONE;
+		if(m_rayTracingShaders.m_rayGenShader)
 		{
-			mask |= (m_shaders[i]) ? shaderTypeToBit(i) : ShaderTypeBit::NONE;
+			if(m_rayTracingShaders.m_rayGenShader->getShaderType() != ShaderType::RAY_GEN)
+			{
+				return false;
+			}
+			rtMask |= ShaderTypeBit::RAY_GEN;
 		}
 
-		U32 invalid = 0;
-		invalid |= !!(mask & ShaderTypeBit::ALL_GRAPHICS) && !!(mask & ~ShaderTypeBit::ALL_GRAPHICS);
-		invalid |= !!(mask & ShaderTypeBit::COMPUTE) && !!(mask & ~ShaderTypeBit::COMPUTE);
+		if(m_rayTracingShaders.m_missShader)
+		{
+			if(m_rayTracingShaders.m_missShader->getShaderType() != ShaderType::MISS)
+			{
+				return false;
+			}
+			rtMask |= ShaderTypeBit::MISS;
+		}
+
+		for(const RayTracingHitGroup& group : m_rayTracingShaders.m_hitGroups)
+		{
+			ShaderTypeBit localRtMask = ShaderTypeBit::NONE;
+			if(group.m_anyHitShader)
+			{
+				if(group.m_anyHitShader->getShaderType() != ShaderType::ANY_HIT)
+				{
+					return false;
+				}
+				localRtMask |= ShaderTypeBit::ANY_HIT;
+			}
+
+			if(group.m_closestHitShader)
+			{
+				if(group.m_closestHitShader->getShaderType() != ShaderType::CLOSEST_HIT)
+				{
+					return false;
+				}
+				localRtMask |= ShaderTypeBit::CLOSEST_HIT;
+			}
+
+			if(!localRtMask)
+			{
+				return false;
+			}
+
+			rtMask |= localRtMask;
+		}
+
+		if(!!rtMask && (!!graphicsMask || compute))
+		{
+			return false;
+		}
 
-		return invalid == 0;
+		return true;
 	}
 };
 

+ 1 - 1
src/anki/gr/vulkan/CommandBufferImpl.inl.h

@@ -762,7 +762,7 @@ inline void CommandBufferImpl::bindShaderProgram(ShaderProgramPtr& prog)
 				 ANY_OTHER_COMMAND);
 	}
 
-	for(U i = 0; i < MAX_DESCRIPTOR_SETS; ++i)
+	for(U32 i = 0; i < MAX_DESCRIPTOR_SETS; ++i)
 	{
 		if(impl.getReflectionInfo().m_descriptorSetMask.get(i))
 		{

+ 135 - 34
src/anki/gr/vulkan/ShaderProgramImpl.cpp

@@ -14,22 +14,64 @@ namespace anki
 
 ShaderProgramImpl::~ShaderProgramImpl()
 {
-	if(m_pplineFactory)
+	if(m_graphics.m_pplineFactory)
 	{
-		m_pplineFactory->destroy();
-		getAllocator().deleteInstance(m_pplineFactory);
+		m_graphics.m_pplineFactory->destroy();
+		getAllocator().deleteInstance(m_graphics.m_pplineFactory);
 	}
 
-	if(m_computePpline)
+	if(m_compute.m_ppline)
 	{
-		vkDestroyPipeline(getDevice(), m_computePpline, nullptr);
+		vkDestroyPipeline(getDevice(), m_compute.m_ppline, nullptr);
 	}
+
+	m_shaders.destroy(getAllocator());
 }
 
 Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 {
 	ANKI_ASSERT(inf.isValid());
-	m_shaders = inf.m_shaders;
+
+	// Create the shader references
+	//
+	if(inf.m_computeShader)
+	{
+		m_shaders.emplaceBack(getAllocator(), inf.m_computeShader);
+	}
+	else if(inf.m_graphicsShaders[ShaderType::VERTEX])
+	{
+		for(const ShaderPtr& s : inf.m_graphicsShaders)
+		{
+			if(s)
+			{
+				m_shaders.emplaceBack(getAllocator(), s);
+			}
+		}
+	}
+	else
+	{
+		// Ray tracing
+
+		m_shaders.resizeStorage(getAllocator(), 2 + inf.m_rayTracingShaders.m_hitGroups.getSize());
+
+		m_shaders.emplaceBack(getAllocator(), inf.m_rayTracingShaders.m_rayGenShader);
+		m_shaders.emplaceBack(getAllocator(), inf.m_rayTracingShaders.m_missShader);
+
+		for(const RayTracingHitGroup& group : inf.m_rayTracingShaders.m_hitGroups)
+		{
+			if(group.m_anyHitShader)
+			{
+				m_shaders.emplaceBack(getAllocator(), group.m_anyHitShader);
+			}
+
+			if(group.m_closestHitShader)
+			{
+				m_shaders.emplaceBack(getAllocator(), group.m_closestHitShader);
+			}
+		}
+	}
+
+	ANKI_ASSERT(m_shaders.getSize() > 0);
 
 	// Merge bindings
 	//
@@ -38,16 +80,11 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	U32 descriptorSetCount = 0;
 	for(U32 set = 0; set < MAX_DESCRIPTOR_SETS; ++set)
 	{
-		for(ShaderType stype = ShaderType::FIRST; stype < ShaderType::COUNT; ++stype)
+		for(ShaderPtr& shader : m_shaders)
 		{
-			if(!m_shaders[stype].isCreated())
-			{
-				continue;
-			}
+			m_stages |= ShaderTypeBit(1 << shader->getShaderType());
 
-			m_stages |= ShaderTypeBit(1 << stype);
-
-			const ShaderImpl& simpl = *static_cast<const ShaderImpl*>(m_shaders[stype].get());
+			const ShaderImpl& simpl = static_cast<const ShaderImpl&>(*shader);
 
 			m_refl.m_activeBindingMask[set] |= simpl.m_activeBindingMask[set];
 
@@ -121,12 +158,14 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	const Bool graphicsProg = !!(m_stages & ShaderTypeBit::ALL_GRAPHICS);
 	if(graphicsProg)
 	{
-		m_refl.m_attributeMask = static_cast<const ShaderImpl*>(m_shaders[ShaderType::VERTEX].get())->m_attributeMask;
+		m_refl.m_attributeMask =
+			static_cast<const ShaderImpl&>(*inf.m_graphicsShaders[ShaderType::VERTEX]).m_attributeMask;
+
 		m_refl.m_colorAttachmentWritemask =
-			static_cast<const ShaderImpl*>(m_shaders[ShaderType::FRAGMENT].get())->m_colorAttachmentWritemask;
+			static_cast<const ShaderImpl&>(*inf.m_graphicsShaders[ShaderType::FRAGMENT]).m_colorAttachmentWritemask;
 
-		const U attachmentCount = m_refl.m_colorAttachmentWritemask.getEnabledBitCount();
-		for(U i = 0; i < attachmentCount; ++i)
+		const U32 attachmentCount = m_refl.m_colorAttachmentWritemask.getEnabledBitCount();
+		for(U32 i = 0; i < attachmentCount; ++i)
 		{
 			ANKI_ASSERT(m_refl.m_colorAttachmentWritemask.get(i) && "Should write to all attachments");
 		}
@@ -136,19 +175,14 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	if(graphicsProg)
 	{
-		for(ShaderType stype = ShaderType::VERTEX; stype <= ShaderType::FRAGMENT; ++stype)
+		for(const ShaderPtr& shader : m_shaders)
 		{
-			if(!m_shaders[stype].isCreated())
-			{
-				continue;
-			}
+			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*shader);
 
-			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*m_shaders[stype]);
-
-			VkPipelineShaderStageCreateInfo& inf = m_shaderCreateInfos[m_shaderCreateInfoCount++];
+			VkPipelineShaderStageCreateInfo& inf = m_graphics.m_shaderCreateInfos[m_graphics.m_shaderCreateInfoCount++];
 			inf = {};
 			inf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
-			inf.stage = convertShaderTypeBit(static_cast<ShaderTypeBit>(1 << stype));
+			inf.stage = convertShaderTypeBit(ShaderTypeBit(1 << shader->getShaderType()));
 			inf.pName = "main";
 			inf.module = shaderImpl.m_handle;
 			inf.pSpecializationInfo = shaderImpl.getSpecConstInfo();
@@ -159,16 +193,16 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	if(graphicsProg)
 	{
-		m_pplineFactory = getAllocator().newInstance<PipelineFactory>();
-		m_pplineFactory->init(getGrManagerImpl().getAllocator(), getGrManagerImpl().getDevice(),
-							  getGrManagerImpl().getPipelineCache());
+		m_graphics.m_pplineFactory = getAllocator().newInstance<PipelineFactory>();
+		m_graphics.m_pplineFactory->init(getGrManagerImpl().getAllocator(), getGrManagerImpl().getDevice(),
+										 getGrManagerImpl().getPipelineCache());
 	}
 
 	// Create the pipeline if compute
 	//
-	if(!graphicsProg)
+	if(!!(m_stages & ShaderTypeBit::COMPUTE))
 	{
-		const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*m_shaders[ShaderType::COMPUTE]);
+		const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*m_shaders[0]);
 
 		VkComputePipelineCreateInfo ci = {};
 		ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
@@ -181,8 +215,75 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		ci.stage.pSpecializationInfo = shaderImpl.getSpecConstInfo();
 
 		ANKI_VK_CHECK(vkCreateComputePipelines(getDevice(), getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr,
-											   &m_computePpline));
-		getGrManagerImpl().printPipelineShaderInfo(m_computePpline, getName(), ShaderTypeBit::COMPUTE);
+											   &m_compute.m_ppline));
+		getGrManagerImpl().printPipelineShaderInfo(m_compute.m_ppline, getName(), ShaderTypeBit::COMPUTE);
+	}
+
+	// Create the RT pipeline
+	//
+	if(!!(m_stages & ShaderTypeBit::ALL_RAY_TRACING))
+	{
+		// Create shaders
+		DynamicArrayAuto<VkPipelineShaderStageCreateInfo> stages(getAllocator(), m_shaders.getSize());
+		for(U32 i = 0; i < stages.getSize(); ++i)
+		{
+			const ShaderImpl& impl = static_cast<const ShaderImpl&>(*m_shaders[i]);
+
+			VkPipelineShaderStageCreateInfo& stage = stages[i];
+			stage = {};
+			stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+			stage.stage = convertShaderTypeBit(ShaderTypeBit(1 << impl.getShaderType()));
+			stage.pName = "main";
+			stage.module = impl.m_handle;
+			stage.pSpecializationInfo = impl.getSpecConstInfo();
+		}
+
+		// Create groups
+		VkRayTracingShaderGroupCreateInfoKHR defaultGroup = {};
+		defaultGroup.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+		defaultGroup.generalShader = VK_SHADER_UNUSED_KHR;
+		defaultGroup.closestHitShader = VK_SHADER_UNUSED_KHR;
+		defaultGroup.anyHitShader = VK_SHADER_UNUSED_KHR;
+		defaultGroup.intersectionShader = VK_SHADER_UNUSED_KHR;
+
+		DynamicArrayAuto<VkRayTracingShaderGroupCreateInfoKHR> groups(
+			getAllocator(), 2 + inf.m_rayTracingShaders.m_hitGroups.getSize(), defaultGroup);
+
+		// 1st group is the ray gen
+		groups[0].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
+		groups[0].generalShader = 0;
+
+		// 2nd group is the miss
+		groups[1].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
+		groups[1].generalShader = 1;
+
+		// The rest of the groups are hit
+		for(U32 i = 0; i < inf.m_rayTracingShaders.m_hitGroups.getSize(); ++i)
+		{
+			groups[i + 2].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
+			if(inf.m_rayTracingShaders.m_hitGroups[i].m_anyHitShader)
+			{
+				groups[i + 2].anyHitShader = i + 2;
+			}
+			else
+			{
+				ANKI_ASSERT(inf.m_rayTracingShaders.m_hitGroups[i].m_closestHitShader);
+				groups[i + 2].closestHitShader = i + 2;
+			}
+		}
+
+		VkRayTracingPipelineCreateInfoKHR ci = {};
+		ci.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
+		ci.stageCount = stages.getSize();
+		ci.pStages = &stages[0];
+		ci.groupCount = groups.getSize();
+		ci.pGroups = &groups[0];
+		ci.maxRecursionDepth = 1;
+		ci.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
+		ci.layout = m_pplineLayout.getHandle();
+
+		ANKI_VK_CHECK(vkCreateRayTracingPipelinesKHR(getDevice(), getGrManagerImpl().getPipelineCache(), 1, &ci,
+													 nullptr, &m_rt.m_rtPpline));
 	}
 
 	return Error::NONE;

+ 27 - 14
src/anki/gr/vulkan/ShaderProgramImpl.h

@@ -43,14 +43,14 @@ public:
 
 	Bool isGraphics() const
 	{
-		return m_pplineFactory != nullptr;
+		return !!(m_stages & ShaderTypeBit::ALL_GRAPHICS);
 	}
 
 	const VkPipelineShaderStageCreateInfo* getShaderCreateInfos(U32& count) const
 	{
 		ANKI_ASSERT(isGraphics());
-		count = m_shaderCreateInfoCount;
-		return &m_shaderCreateInfos[0];
+		count = m_graphics.m_shaderCreateInfoCount;
+		return &m_graphics.m_shaderCreateInfos[0];
 	}
 
 	const PipelineLayout& getPipelineLayout() const
@@ -58,7 +58,7 @@ public:
 		return m_pplineLayout;
 	}
 
-	const DescriptorSetLayout& getDescriptorSetLayout(U set) const
+	const DescriptorSetLayout& getDescriptorSetLayout(U32 set) const
 	{
 		ANKI_ASSERT(m_descriptorSetLayouts[set].isCreated());
 		return m_descriptorSetLayouts[set];
@@ -72,14 +72,14 @@ public:
 	/// Only for graphics programs.
 	PipelineFactory& getPipelineFactory()
 	{
-		ANKI_ASSERT(m_pplineFactory);
-		return *m_pplineFactory;
+		ANKI_ASSERT(m_graphics.m_pplineFactory);
+		return *m_graphics.m_pplineFactory;
 	}
 
 	VkPipeline getComputePipelineHandle() const
 	{
-		ANKI_ASSERT(m_computePpline);
-		return m_computePpline;
+		ANKI_ASSERT(m_compute.m_ppline);
+		return m_compute.m_ppline;
 	}
 
 	ShaderTypeBit getStages() const
@@ -89,20 +89,33 @@ public:
 	}
 
 private:
-	Array<ShaderPtr, U32(ShaderType::COUNT)> m_shaders;
+	DynamicArray<ShaderPtr> m_shaders;
 	ShaderTypeBit m_stages = ShaderTypeBit::NONE;
 
-	Array<VkPipelineShaderStageCreateInfo, U32(ShaderType::FRAGMENT - ShaderType::VERTEX) + 1> m_shaderCreateInfos;
-	U32 m_shaderCreateInfoCount = 0;
-
 	PipelineLayout m_pplineLayout = {};
 	Array<DescriptorSetLayout, MAX_DESCRIPTOR_SETS> m_descriptorSetLayouts;
 
 	ShaderProgramReflectionInfo m_refl;
 
-	PipelineFactory* m_pplineFactory = nullptr; ///< Only for graphics programs.
+	class
+	{
+	public:
+		Array<VkPipelineShaderStageCreateInfo, U32(ShaderType::FRAGMENT - ShaderType::VERTEX) + 1> m_shaderCreateInfos;
+		U32 m_shaderCreateInfoCount = 0;
+		PipelineFactory* m_pplineFactory = nullptr;
+	} m_graphics;
 
-	VkPipeline m_computePpline = VK_NULL_HANDLE;
+	class
+	{
+	public:
+		VkPipeline m_ppline = VK_NULL_HANDLE;
+	} m_compute;
+
+	class
+	{
+	public:
+		VkPipeline m_rtPpline = VK_NULL_HANDLE;
+	} m_rt;
 };
 /// @}
 

+ 14 - 1
src/anki/resource/ShaderProgramResource.cpp

@@ -369,8 +369,21 @@ void ShaderProgramResource::initVariant(const ShaderProgramResourceVariantInitIn
 		inf.m_shaderType = shaderType;
 		inf.m_binary = binary.m_codeBlocks[binaryVariant->m_codeBlockIndices[shaderType]].m_binary;
 		inf.m_constValues.setArray((constValueCount) ? constValues.getBegin() : nullptr, constValueCount);
+		ShaderPtr shader = getManager().getGrManager().newShader(inf);
 
-		progInf.m_shaders[shaderType] = getManager().getGrManager().newShader(inf);
+		const ShaderTypeBit shaderBit = ShaderTypeBit(1 << shaderType);
+		if(!!(shaderBit & ShaderTypeBit::ALL_GRAPHICS))
+		{
+			progInf.m_graphicsShaders[shaderType] = shader;
+		}
+		else if(shaderType == ShaderType::COMPUTE)
+		{
+			progInf.m_computeShader = shader;
+		}
+		else
+		{
+			ANKI_ASSERT(!"TODO");
+		}
 	}
 
 	// Create the program

+ 15 - 7
tests/gr/Gr.cpp

@@ -378,7 +378,10 @@ static ShaderProgramPtr createProgram(CString vertSrc, CString fragSrc, GrManage
 {
 	ShaderPtr vert = createShader(vertSrc, ShaderType::VERTEX, gr);
 	ShaderPtr frag = createShader(fragSrc, ShaderType::FRAGMENT, gr);
-	return gr.newShaderProgram(ShaderProgramInitInfo(vert, frag));
+	ShaderProgramInitInfo inf;
+	inf.m_graphicsShaders[ShaderType::VERTEX];
+	inf.m_graphicsShaders[ShaderType::FRAGMENT];
+	return gr.newShaderProgram(inf);
 }
 
 static FramebufferPtr createColorFb(GrManager& gr, TexturePtr tex)
@@ -1304,7 +1307,7 @@ ANKI_TEST(Gr, ImageLoadStore)
 	// Create shader & compute prog
 	ShaderPtr shader = createShader(COMP_WRITE_IMAGE_SRC, ShaderType::COMPUTE, *gr);
 	ShaderProgramInitInfo sprogInit;
-	sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+	sprogInit.m_computeShader = shader;
 	ShaderProgramPtr compProg = gr->newShaderProgram(sprogInit);
 
 	// Write texture data
@@ -1755,7 +1758,9 @@ void main()
 })";
 
 	ShaderPtr comp = createShader(COMP_SRC, ShaderType::COMPUTE, *gr);
-	ShaderProgramPtr prog = gr->newShaderProgram(ShaderProgramInitInfo(comp));
+	ShaderProgramInitInfo sinf;
+	sinf.m_computeShader = comp;
+	ShaderProgramPtr prog = gr->newShaderProgram(sinf);
 
 	// Create the texture
 	TextureInitInfo texInit;
@@ -1904,7 +1909,10 @@ void main()
 	ShaderPtr frag = createShader(FRAG_SRC, ShaderType::FRAGMENT, *gr,
 								  Array<ShaderSpecializationConstValue, 2>{{ShaderSpecializationConstValue(-2147483647),
 																			ShaderSpecializationConstValue(-1.0f)}});
-	ShaderProgramPtr prog = gr->newShaderProgram(ShaderProgramInitInfo(vert, frag));
+	ShaderProgramInitInfo sinf;
+	sinf.m_graphicsShaders[ShaderType::VERTEX] = vert;
+	sinf.m_graphicsShaders[ShaderType::FRAGMENT] = frag;
+	ShaderProgramPtr prog = gr->newShaderProgram(sinf);
 
 	// Create the result buffer
 	BufferPtr resultBuff =
@@ -2110,7 +2118,7 @@ void main()
 
 	ShaderPtr shader = createShader(PROG_SRC, ShaderType::COMPUTE, *gr);
 	ShaderProgramInitInfo sprogInit;
-	sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+	sprogInit.m_computeShader = shader;
 	ShaderProgramPtr prog = gr->newShaderProgram(sprogInit);
 
 	// Run
@@ -2207,7 +2215,7 @@ void main()
 
 	ShaderPtr shader = createShader(PROG_SRC, ShaderType::COMPUTE, *gr);
 	ShaderProgramInitInfo sprogInit;
-	sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+	sprogInit.m_computeShader = shader;
 	ShaderProgramPtr prog = gr->newShaderProgram(sprogInit);
 
 	// Run
@@ -2300,7 +2308,7 @@ void main()
 
 	ShaderPtr shader = createShader(PROG_SRC, ShaderType::COMPUTE, *gr);
 	ShaderProgramInitInfo sprogInit;
-	sprogInit.m_shaders[ShaderType::COMPUTE] = shader;
+	sprogInit.m_computeShader = shader;
 	ShaderProgramPtr prog = gr->newShaderProgram(sprogInit);
 
 	// Create buffers