Browse Source

vulkan: add missing layout transitions

niki 3 years ago
parent
commit
8cf7a79657

+ 11 - 9
src/modules/graphics/vulkan/Texture.cpp

@@ -44,7 +44,9 @@ bool Texture::loadVolatile() {
 		throw love::Exception("failed to create image");
 	}
 	// fixme: we should use VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL as the default image layout instead of VK_IMAGE_LAYOUT_GENERAL.
-	transitionImageLayout(textureImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
+	vgfx->queueDatatransfer([textureImage = textureImage](VkCommandBuffer commandBuffer){
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
+	}, nullptr);
 
 	if (data) {
 		auto sliceData = data->get(0, 0);
@@ -211,14 +213,6 @@ VkClearColorValue Texture::getClearValue(bool white) {
 	return clearColor;
 }
 
-void Texture::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) {
-	auto commandBuffer = vgfx->beginSingleTimeCommands();
-
-	Vulkan::cmdTransitionImageLayout(commandBuffer, image, oldLayout, newLayout);
-
-	vgfx->endSingleTimeCommands(commandBuffer);
-}
-
 void Texture::uploadByteData(PixelFormat pixelformat, const void* data, size_t size, int level, int slice, const Rect& r) {
 	VkBuffer stagingBuffer;
 	VmaAllocation vmaAllocation;
@@ -291,7 +285,11 @@ void Texture::copyFromBuffer(graphics::Buffer* source, size_t sourceoffset, int
 		region.imageExtent.width = static_cast<uint32_t>(rect.w);
 		region.imageExtent.height = static_cast<uint32_t>(rect.h);
 
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+
 		vkCmdCopyBufferToImage(commandBuffer, (VkBuffer)source->getHandle(), textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
 	}, nullptr);
 }
 
@@ -311,7 +309,11 @@ void Texture::copyToBuffer(graphics::Buffer* dest, int slice, int mipmap, const
 		region.imageExtent.width = static_cast<uint32_t>(rect.w);
 		region.imageExtent.height = static_cast<uint32_t>(rect.h);
 
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+
 		vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, (VkBuffer) dest->getHandle(), 1, &region);
+
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL);
 	}, nullptr);
 }
 

+ 0 - 1
src/modules/graphics/vulkan/Texture.h

@@ -36,7 +36,6 @@ public:
 	VkSampler getSampler() const { return textureSampler; }
 
 private:
-	void transitionImageLayout(VkImage, VkImageLayout oldLayout, VkImageLayout newLayout);
 	void createTextureImageView();
 	void createTextureSampler();
 	void clear(bool white);

+ 14 - 0
src/modules/graphics/vulkan/Vulkan.cpp

@@ -533,6 +533,20 @@ void Vulkan::cmdTransitionImageLayout(VkCommandBuffer commandBuffer, VkImage ima
 		sourceStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
 		destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
 	}
+	else if (oldLayout == VK_IMAGE_LAYOUT_GENERAL && newLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) {
+		barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+		barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+
+		sourceStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+		destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+	}
+	else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_GENERAL) {
+		barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+		barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+
+		sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
+		destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+	}
 	else {
 		throw std::invalid_argument("unsupported layout transition!");
 	}