Bläddra i källkod

Vulkan: Some bug fixes & testing storage

Panagiotis Christopoulos Charitos 9 år sedan
förälder
incheckning
79b4a54faa

+ 6 - 0
include/anki/gr/vulkan/BufferImpl.h

@@ -54,6 +54,11 @@ public:
 		return m_size;
 		return m_size;
 	}
 	}
 
 
+	Bool usageValid(BufferUsageBit usage) const
+	{
+		return (m_usage & usage) == usage;
+	}
+
 private:
 private:
 	VkBuffer m_handle = VK_NULL_HANDLE;
 	VkBuffer m_handle = VK_NULL_HANDLE;
 	GpuMemoryAllocationHandle m_memHandle;
 	GpuMemoryAllocationHandle m_memHandle;
@@ -61,6 +66,7 @@ private:
 	BufferMapAccessBit m_access = BufferMapAccessBit::NONE;
 	BufferMapAccessBit m_access = BufferMapAccessBit::NONE;
 	U32 m_size = 0;
 	U32 m_size = 0;
 	VkMemoryPropertyFlags m_memoryFlags = 0;
 	VkMemoryPropertyFlags m_memoryFlags = 0;
+	BufferUsageBit m_usage = BufferUsageBit::NONE;
 
 
 #if ANKI_ASSERTIONS
 #if ANKI_ASSERTIONS
 	Bool8 m_mapped = false;
 	Bool8 m_mapped = false;

+ 1 - 0
src/gr/vulkan/BufferImpl.cpp

@@ -137,6 +137,7 @@ Error BufferImpl::init(
 
 
 	m_access = access;
 	m_access = access;
 	m_size = size;
 	m_size = size;
+	m_usage = usage;
 	return ErrorCode::NONE;
 	return ErrorCode::NONE;
 }
 }
 
 

+ 89 - 61
src/gr/vulkan/ResourceGroupImpl.cpp

@@ -92,17 +92,16 @@ U ResourceGroupImpl::calcRefCount(
 
 
 	for(U i = 0; i < MAX_TEXTURE_BINDINGS; ++i)
 	for(U i = 0; i < MAX_TEXTURE_BINDINGS; ++i)
 	{
 	{
-		if(init.m_textures[i].m_texture)
+		const TextureBinding& b = init.m_textures[i];
+		if(b.m_texture)
 		{
 		{
 			++count;
 			++count;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_textures[i].m_usage);
-			ANKI_ASSERT(
-				init.m_textures[i].m_texture->getImplementation().usageValid(
-					init.m_textures[i].m_usage));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(b.m_texture->getImplementation().usageValid(b.m_usage));
 		}
 		}
 
 
-		if(init.m_textures[i].m_sampler)
+		if(b.m_sampler)
 		{
 		{
 			++count;
 			++count;
 			needsDSet = true;
 			needsDSet = true;
@@ -111,72 +110,70 @@ U ResourceGroupImpl::calcRefCount(
 
 
 	for(U i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
 	for(U i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
 	{
 	{
-		if(init.m_uniformBuffers[i].m_buffer)
+		const BufferBinding& b = init.m_uniformBuffers[i];
+		if(b.m_buffer)
 		{
 		{
 			++count;
 			++count;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_uniformBuffers[i].m_usage);
-			ANKI_ASSERT(!!(init.m_uniformBuffers[i].m_usage
-							& BufferUsageBit::UNIFORM_ALL)
-				&& !(init.m_uniformBuffers[i].m_usage
-					   & ~BufferUsageBit::UNIFORM_ALL));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(!!(b.m_usage & BufferUsageBit::UNIFORM_ALL)
+				&& !(b.m_usage & ~BufferUsageBit::UNIFORM_ALL));
+			ANKI_ASSERT(b.m_buffer->getImplementation().usageValid(b.m_usage));
 		}
 		}
-		else if(init.m_uniformBuffers[i].m_uploadedMemory)
+		else if(b.m_uploadedMemory)
 		{
 		{
 			hasUploaded = true;
 			hasUploaded = true;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_uniformBuffers[i].m_usage);
-			ANKI_ASSERT(!!(init.m_uniformBuffers[i].m_usage
-							& BufferUsageBit::UNIFORM_ALL)
-				&& !(init.m_uniformBuffers[i].m_usage
-					   & ~BufferUsageBit::UNIFORM_ALL));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(!!(b.m_usage & BufferUsageBit::UNIFORM_ALL)
+				&& !(b.m_usage & ~BufferUsageBit::UNIFORM_ALL));
 		}
 		}
 	}
 	}
 
 
 	for(U i = 0; i < MAX_STORAGE_BUFFER_BINDINGS; ++i)
 	for(U i = 0; i < MAX_STORAGE_BUFFER_BINDINGS; ++i)
 	{
 	{
-		if(init.m_storageBuffers[i].m_buffer)
+		const BufferBinding& b = init.m_storageBuffers[i];
+		if(b.m_buffer)
 		{
 		{
 			++count;
 			++count;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_storageBuffers[i].m_usage);
-			ANKI_ASSERT(!!(init.m_uniformBuffers[i].m_usage
-							& BufferUsageBit::STORAGE_ALL)
-				&& !(init.m_uniformBuffers[i].m_usage
-					   & ~BufferUsageBit::STORAGE_ALL));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(!!(b.m_usage & BufferUsageBit::STORAGE_ALL)
+				&& !(b.m_usage & ~BufferUsageBit::STORAGE_ALL));
+			ANKI_ASSERT(b.m_buffer->getImplementation().usageValid(b.m_usage));
 		}
 		}
-		else if(init.m_storageBuffers[i].m_uploadedMemory)
+		else if(b.m_uploadedMemory)
 		{
 		{
 			hasUploaded = true;
 			hasUploaded = true;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_storageBuffers[i].m_usage);
-			ANKI_ASSERT(!!(init.m_uniformBuffers[i].m_usage
-							& BufferUsageBit::STORAGE_ALL)
-				&& !(init.m_uniformBuffers[i].m_usage
-					   & ~BufferUsageBit::STORAGE_ALL));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(!!(b.m_usage & BufferUsageBit::STORAGE_ALL)
+				&& !(b.m_usage & ~BufferUsageBit::STORAGE_ALL));
 		}
 		}
 	}
 	}
 
 
 	for(U i = 0; i < MAX_IMAGE_BINDINGS; ++i)
 	for(U i = 0; i < MAX_IMAGE_BINDINGS; ++i)
 	{
 	{
-		if(init.m_images[i].m_texture)
+		const ImageBinding& b = init.m_images[i];
+		if(b.m_texture)
 		{
 		{
 			++count;
 			++count;
 			needsDSet = true;
 			needsDSet = true;
-			updateBindPoint(init.m_images[i].m_usage);
-			ANKI_ASSERT(
-				init.m_images[i].m_texture->getImplementation().usageValid(
-					init.m_textures[i].m_usage));
+			updateBindPoint(b.m_usage);
+			ANKI_ASSERT(b.m_texture->getImplementation().usageValid(b.m_usage));
 		}
 		}
 	}
 	}
 
 
 	for(U i = 0; i < MAX_VERTEX_ATTRIBUTES; ++i)
 	for(U i = 0; i < MAX_VERTEX_ATTRIBUTES; ++i)
 	{
 	{
-		if(init.m_vertexBuffers[i].m_buffer)
+		const BufferBinding& b = init.m_vertexBuffers[i];
+		if(b.m_buffer)
 		{
 		{
 			++count;
 			++count;
+			ANKI_ASSERT(b.m_buffer->getImplementation().usageValid(
+				BufferUsageBit::VERTEX));
 		}
 		}
-		else if(init.m_vertexBuffers[i].m_uploadedMemory)
+		else if(b.m_uploadedMemory)
 		{
 		{
 			hasUploaded = true;
 			hasUploaded = true;
 		}
 		}
@@ -184,6 +181,8 @@ U ResourceGroupImpl::calcRefCount(
 
 
 	if(init.m_indexBuffer.m_buffer)
 	if(init.m_indexBuffer.m_buffer)
 	{
 	{
+		ANKI_ASSERT(init.m_indexBuffer.m_buffer->getImplementation().usageValid(
+			BufferUsageBit::INDEX));
 		++count;
 		++count;
 	}
 	}
 
 
@@ -215,22 +214,21 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 	// Update
 	// Update
 	//
 	//
 	Array<VkDescriptorImageInfo, MAX_TEXTURE_BINDINGS> texes = {{}};
 	Array<VkDescriptorImageInfo, MAX_TEXTURE_BINDINGS> texes = {{}};
-	U texAndSamplerCount = 0;
 	Array<VkDescriptorBufferInfo, MAX_UNIFORM_BUFFER_BINDINGS> unis = {{}};
 	Array<VkDescriptorBufferInfo, MAX_UNIFORM_BUFFER_BINDINGS> unis = {{}};
-	U uniCount = 0;
 	Array<VkDescriptorBufferInfo, MAX_STORAGE_BUFFER_BINDINGS> storages = {{}};
 	Array<VkDescriptorBufferInfo, MAX_STORAGE_BUFFER_BINDINGS> storages = {{}};
-	U storageCount = 0;
 	Array<VkDescriptorImageInfo, MAX_IMAGE_BINDINGS> images = {{}};
 	Array<VkDescriptorImageInfo, MAX_IMAGE_BINDINGS> images = {{}};
-	U imageCount = 0;
 	Array<VkWriteDescriptorSet, 4> write = {{}};
 	Array<VkWriteDescriptorSet, 4> write = {{}};
 	U writeCount = 0;
 	U writeCount = 0;
 	refCount = 0;
 	refCount = 0;
+	Bool hole = false;
+	U count = 0;
 
 
 	// 1st the textures
 	// 1st the textures
 	for(U i = 0; i < MAX_TEXTURE_BINDINGS; ++i)
 	for(U i = 0; i < MAX_TEXTURE_BINDINGS; ++i)
 	{
 	{
 		if(init.m_textures[i].m_texture)
 		if(init.m_textures[i].m_texture)
 		{
 		{
+			ANKI_ASSERT(!hole);
 			TextureImpl& teximpl =
 			TextureImpl& teximpl =
 				init.m_textures[i].m_texture->getImplementation();
 				init.m_textures[i].m_texture->getImplementation();
 
 
@@ -255,15 +253,19 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 			inf.imageLayout =
 			inf.imageLayout =
 				teximpl.computeLayout(init.m_textures[i].m_usage, 0);
 				teximpl.computeLayout(init.m_textures[i].m_usage, 0);
 
 
-			++texAndSamplerCount;
+			++count;
+		}
+		else
+		{
+			hole = true;
 		}
 		}
 	}
 	}
 
 
-	if(texAndSamplerCount)
+	if(count)
 	{
 	{
 		VkWriteDescriptorSet& w = write[writeCount++];
 		VkWriteDescriptorSet& w = write[writeCount++];
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-		w.descriptorCount = texAndSamplerCount;
+		w.descriptorCount = count;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
 		w.dstBinding = 0;
 		w.dstBinding = 0;
 		w.pImageInfo = &texes[0];
 		w.pImageInfo = &texes[0];
@@ -271,11 +273,14 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 	}
 	}
 
 
 	// 2nd the uniform buffers
 	// 2nd the uniform buffers
+	count = 0;
+	hole = false;
 	for(U i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
 	for(U i = 0; i < MAX_UNIFORM_BUFFER_BINDINGS; ++i)
 	{
 	{
 		if(init.m_uniformBuffers[i].m_buffer)
 		if(init.m_uniformBuffers[i].m_buffer)
 		{
 		{
-			VkDescriptorBufferInfo& inf = unis[uniCount++];
+			ANKI_ASSERT(!hole);
+			VkDescriptorBufferInfo& inf = unis[i];
 			inf.buffer = init.m_uniformBuffers[i]
 			inf.buffer = init.m_uniformBuffers[i]
 							 .m_buffer->getImplementation()
 							 .m_buffer->getImplementation()
 							 .getHandle();
 							 .getHandle();
@@ -288,11 +293,12 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 
 
 			m_refs[refCount++] = init.m_uniformBuffers[i].m_buffer;
 			m_refs[refCount++] = init.m_uniformBuffers[i].m_buffer;
 
 
-			m_uniBindingCount = i + 1;
+			++count;
 		}
 		}
 		else if(init.m_uniformBuffers[i].m_uploadedMemory)
 		else if(init.m_uniformBuffers[i].m_uploadedMemory)
 		{
 		{
-			VkDescriptorBufferInfo& inf = unis[uniCount++];
+			ANKI_ASSERT(!hole);
+			VkDescriptorBufferInfo& inf = unis[i];
 			inf.buffer =
 			inf.buffer =
 				getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
 				getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
 					BufferUsageBit::UNIFORM_ALL);
 					BufferUsageBit::UNIFORM_ALL);
@@ -300,27 +306,36 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 
 
 			m_dynamicBuffersMask.set(i);
 			m_dynamicBuffersMask.set(i);
 
 
-			m_uniBindingCount = i + 1;
+			++count;
+		}
+		else
+		{
+			hole = true;
 		}
 		}
 	}
 	}
 
 
-	if(uniCount)
+	if(count)
 	{
 	{
 		VkWriteDescriptorSet& w = write[writeCount++];
 		VkWriteDescriptorSet& w = write[writeCount++];
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-		w.descriptorCount = uniCount;
+		w.descriptorCount = count;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
 		w.dstBinding = MAX_TEXTURE_BINDINGS;
 		w.dstBinding = MAX_TEXTURE_BINDINGS;
 		w.pBufferInfo = &unis[0];
 		w.pBufferInfo = &unis[0];
 		w.dstSet = m_handle;
 		w.dstSet = m_handle;
 	}
 	}
 
 
+	m_uniBindingCount = count;
+
 	// 3nd the storage buffers
 	// 3nd the storage buffers
+	count = 0;
+	hole = false;
 	for(U i = 0; i < MAX_STORAGE_BUFFER_BINDINGS; ++i)
 	for(U i = 0; i < MAX_STORAGE_BUFFER_BINDINGS; ++i)
 	{
 	{
 		if(init.m_storageBuffers[i].m_buffer)
 		if(init.m_storageBuffers[i].m_buffer)
 		{
 		{
-			VkDescriptorBufferInfo& inf = storages[storageCount++];
+			ANKI_ASSERT(!hole);
+			VkDescriptorBufferInfo& inf = storages[i];
 			inf.buffer = init.m_storageBuffers[i]
 			inf.buffer = init.m_storageBuffers[i]
 							 .m_buffer->getImplementation()
 							 .m_buffer->getImplementation()
 							 .getHandle();
 							 .getHandle();
@@ -332,41 +347,49 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 			}
 			}
 
 
 			m_refs[refCount++] = init.m_storageBuffers[i].m_buffer;
 			m_refs[refCount++] = init.m_storageBuffers[i].m_buffer;
-
-			m_storageBindingCount = i + 1;
+			++count;
 		}
 		}
 		else if(init.m_storageBuffers[i].m_uploadedMemory)
 		else if(init.m_storageBuffers[i].m_uploadedMemory)
 		{
 		{
-			VkDescriptorBufferInfo& inf = storages[storageCount++];
+			ANKI_ASSERT(!hole);
+			VkDescriptorBufferInfo& inf = storages[i];
 			inf.buffer =
 			inf.buffer =
 				getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
 				getGrManagerImpl().getTransientMemoryManager().getBufferHandle(
 					BufferUsageBit::STORAGE_ALL);
 					BufferUsageBit::STORAGE_ALL);
 			inf.range = VK_WHOLE_SIZE;
 			inf.range = VK_WHOLE_SIZE;
 
 
 			m_dynamicBuffersMask.set(MAX_UNIFORM_BUFFER_BINDINGS + i);
 			m_dynamicBuffersMask.set(MAX_UNIFORM_BUFFER_BINDINGS + i);
-
-			m_storageBindingCount = i + 1;
+			++count;
+		}
+		else
+		{
+			hole = true;
 		}
 		}
 	}
 	}
 
 
-	if(storageCount)
+	if(count)
 	{
 	{
 		VkWriteDescriptorSet& w = write[writeCount++];
 		VkWriteDescriptorSet& w = write[writeCount++];
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-		w.descriptorCount = storageCount;
+		w.descriptorCount = count;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
 		w.dstBinding = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS;
 		w.dstBinding = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS;
 		w.pBufferInfo = &storages[0];
 		w.pBufferInfo = &storages[0];
 		w.dstSet = m_handle;
 		w.dstSet = m_handle;
 	}
 	}
 
 
+	m_storageBindingCount = count;
+
 	// 4th images
 	// 4th images
+	count = 0;
+	hole = false;
 	for(U i = 0; i < MAX_IMAGE_BINDINGS; ++i)
 	for(U i = 0; i < MAX_IMAGE_BINDINGS; ++i)
 	{
 	{
 		const ImageBinding& binding = init.m_images[i];
 		const ImageBinding& binding = init.m_images[i];
 		if(binding.m_texture)
 		if(binding.m_texture)
 		{
 		{
-			VkDescriptorImageInfo& inf = images[imageCount++];
+			ANKI_ASSERT(!hole);
+			VkDescriptorImageInfo& inf = images[i];
 			const TextureImpl& tex = binding.m_texture->getImplementation();
 			const TextureImpl& tex = binding.m_texture->getImplementation();
 
 
 			if(binding.m_level == 0)
 			if(binding.m_level == 0)
@@ -380,14 +403,19 @@ Error ResourceGroupImpl::init(const ResourceGroupInitInfo& init)
 			inf.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 			inf.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
 
 			m_refs[refCount++] = binding.m_texture;
 			m_refs[refCount++] = binding.m_texture;
+			++count;
+		}
+		else
+		{
+			hole = true;
 		}
 		}
 	}
 	}
 
 
-	if(imageCount)
+	if(count)
 	{
 	{
 		VkWriteDescriptorSet& w = write[writeCount++];
 		VkWriteDescriptorSet& w = write[writeCount++];
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
 		w.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
-		w.descriptorCount = imageCount;
+		w.descriptorCount = count;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
 		w.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
 		w.dstBinding = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS
 		w.dstBinding = MAX_TEXTURE_BINDINGS + MAX_UNIFORM_BUFFER_BINDINGS
 			+ MAX_STORAGE_BUFFER_BINDINGS;
 			+ MAX_STORAGE_BUFFER_BINDINGS;

+ 22 - 3
tests/gr/Gr.cpp

@@ -246,10 +246,14 @@ layout(local_size_x = 1,
 	local_size_y = 1,
 	local_size_y = 1,
 	local_size_z = 1) in;
 	local_size_z = 1) in;
 	
 	
+layout(ANKI_SS_BINDING(1, 0)) buffer ss1_
+{
+	vec4 u_color;
+};
+	
 void main()
 void main()
 {
 {
-	vec4 col = vec4(1.0, 0.0, 0.0, 0.0);
-	imageStore(u_img, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), col);
+	imageStore(u_img, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), u_color);
 })";
 })";
 
 
 #define COMMON_BEGIN()                                                         \
 #define COMMON_BEGIN()                                                         \
@@ -1325,6 +1329,12 @@ ANKI_TEST(Gr, ImageLoadStore)
 		rcinit.m_images[0].m_level = 1;
 		rcinit.m_images[0].m_level = 1;
 		ResourceGroupPtr rc1 = gr->newInstance<ResourceGroup>(rcinit);
 		ResourceGroupPtr rc1 = gr->newInstance<ResourceGroup>(rcinit);
 
 
+		rcinit = ResourceGroupInitInfo();
+		rcinit.m_storageBuffers[0].m_uploadedMemory = true;
+		rcinit.m_storageBuffers[0].m_usage =
+			BufferUsageBit::STORAGE_COMPUTE_READ;
+		ResourceGroupPtr rc2 = gr->newInstance<ResourceGroup>(rcinit);
+
 		// FB
 		// FB
 		FramebufferPtr dfb = createDefaultFb(*gr);
 		FramebufferPtr dfb = createDefaultFb(*gr);
 
 
@@ -1372,13 +1382,22 @@ ANKI_TEST(Gr, ImageLoadStore)
 			CommandBufferInitInfo cinit;
 			CommandBufferInitInfo cinit;
 			CommandBufferPtr cmdb = gr->newInstance<CommandBuffer>(cinit);
 			CommandBufferPtr cmdb = gr->newInstance<CommandBuffer>(cinit);
 
 
-			// Write iamge
+			// Write image
+			TransientMemoryInfo trans;
+			Vec4* col = static_cast<Vec4*>(
+				gr->allocateFrameTransientMemory(sizeof(*col),
+					BufferUsageBit::STORAGE_ALL,
+					trans.m_storageBuffers[0],
+					nullptr));
+			*col = Vec4(iterations / F32(ITERATION_COUNT));
+
 			cmdb->setTextureBarrier(tex,
 			cmdb->setTextureBarrier(tex,
 				TextureUsageBit::NONE,
 				TextureUsageBit::NONE,
 				TextureUsageBit::IMAGE_COMPUTE_WRITE,
 				TextureUsageBit::IMAGE_COMPUTE_WRITE,
 				TextureSurfaceInfo(1, 0, 0, 0));
 				TextureSurfaceInfo(1, 0, 0, 0));
 			cmdb->bindPipeline(compPpline);
 			cmdb->bindPipeline(compPpline);
 			cmdb->bindResourceGroup(rc1, 0, nullptr);
 			cmdb->bindResourceGroup(rc1, 0, nullptr);
+			cmdb->bindResourceGroup(rc2, 1, &trans);
 			cmdb->dispatchCompute(WIDTH / 2, HEIGHT / 2, 1);
 			cmdb->dispatchCompute(WIDTH / 2, HEIGHT / 2, 1);
 			cmdb->setTextureBarrier(tex,
 			cmdb->setTextureBarrier(tex,
 				TextureUsageBit::IMAGE_COMPUTE_WRITE,
 				TextureUsageBit::IMAGE_COMPUTE_WRITE,