Browse Source

vulkan: fix canvas rendering (on android)
Before this patch, sometimes rendering a texture
on an android device would result in random things
appearing in the canvas, apart from the stuff
that has been drawn properly.
With these changes this does not seem to appear anymore.

niki 3 years ago
parent
commit
d123021e26

+ 26 - 17
src/modules/graphics/vulkan/Graphics.cpp

@@ -126,6 +126,19 @@ void Graphics::clear(const std::vector<OptionalColorD>& colors, OptionalInt sten
 		attachments.push_back(attachment);
 	}
 
+	VkClearAttachment depthStencilAttachment{};
+
+	if (stencil.hasValue) {
+		depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
+		depthStencilAttachment.clearValue.depthStencil.stencil = static_cast<uint32_t>(stencil.value);
+	}
+	if (depth.hasValue) {
+		depthStencilAttachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+		depthStencilAttachment.clearValue.depthStencil.depth = static_cast<float>(depth.value);
+	}
+
+	attachments.push_back(depthStencilAttachment);
+
 	VkClearRect rect{};
 	rect.layerCount = 1;
 	rect.rect.extent.width = static_cast<uint32_t>(currentViewportWidth);
@@ -1242,6 +1255,7 @@ void Graphics::createImageViews() {
 void Graphics::createDefaultRenderPass() {
 	RenderPassConfiguration renderPassConfiguration{};
 	renderPassConfiguration.colorFormats.push_back(swapChainImageFormat);
+	renderPassConfiguration.staticData.initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 	renderPassConfiguration.staticData.msaaSamples = msaaSamples;
 	renderPassConfiguration.staticData.depthFormat = findDepthFormat();
 	renderPassConfiguration.staticData.resolve = true;
@@ -1336,11 +1350,11 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration configuration) {
 		VkAttachmentDescription colorDescription{};
 		colorDescription.format = colorFormat;
 		colorDescription.samples = configuration.staticData.msaaSamples;
-		colorDescription.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+		colorDescription.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
 		colorDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
 		colorDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
 		colorDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
-		colorDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+		colorDescription.initialLayout = configuration.staticData.initialColorImageLayout;
 		colorDescription.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 		attachments.push_back(colorDescription);
 	}
@@ -1387,8 +1401,8 @@ VkRenderPass Graphics::createRenderPass(RenderPassConfiguration configuration) {
 	VkSubpassDependency dependency{};
 	dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
 	dependency.dstSubpass = 0;
-	dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
-	dependency.srcAccessMask = 0;
+	dependency.srcStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
+	dependency.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
 	dependency.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
 	dependency.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
 
@@ -1553,12 +1567,10 @@ void Graphics::startDefaultRenderPass() {
 void Graphics::startRenderPass(const RenderTargets& rts, int pixelw, int pixelh, bool hasSRGBtexture) {
 	auto currentCommandBuffer = commandBuffers.at(currentFrame);
 
-	auto width = static_cast<uint32_t>(rts.getFirstTarget().texture->getWidth());
-	auto height = static_cast<uint32_t>(rts.getFirstTarget().texture->getHeight());
-
 	// fixme: hasSRGBtexture
 	// fixme: msaaSamples
 	RenderPassConfiguration renderPassConfiguration{};
+	renderPassConfiguration.staticData.initialColorImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
 	for (const auto &color : rts.colors) {
 		// fixme: use mipmap and slice.
 		color.mipmap;
@@ -1593,13 +1605,13 @@ void Graphics::startRenderPass(const RenderTargets& rts, int pixelw, int pixelh,
 		transitionBackImages.push_back((VkImage) color.texture->getHandle());
 	}
 	if (rts.depthStencil.texture != nullptr) {
-		configuration.colorViews.push_back((VkImageView)rts.depthStencil.texture->getRenderTargetHandle());
+		configuration.staticData.depthView = (VkImageView)rts.depthStencil.texture->getRenderTargetHandle();
 		// fixme: layout transition of depth stencil image?
 	}
 
 	configuration.staticData.renderPass = renderPass;
-	configuration.staticData.width = static_cast<uint32_t>(width);
-	configuration.staticData.height = static_cast<uint32_t>(height);
+	configuration.staticData.width = static_cast<uint32_t>(pixelw);
+	configuration.staticData.height = static_cast<uint32_t>(pixelh);
 	VkFramebuffer framebuffer = getFramebuffer(configuration);
 
     VkRenderPassBeginInfo renderPassInfo{};
@@ -1607,15 +1619,15 @@ void Graphics::startRenderPass(const RenderTargets& rts, int pixelw, int pixelh,
     renderPassInfo.renderPass = renderPass;
 	renderPassInfo.framebuffer = framebuffer;
     renderPassInfo.renderArea.offset = {0, 0};
-    renderPassInfo.renderArea.extent.width = static_cast<uint32_t>(width);
-    renderPassInfo.renderArea.extent.height = static_cast<uint32_t>(height);
+    renderPassInfo.renderArea.extent.width = static_cast<uint32_t>(pixelw);
+    renderPassInfo.renderArea.extent.height = static_cast<uint32_t>(pixelh);
 
     vkCmdBeginRenderPass(currentCommandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
 
     currentRenderPass = renderPass;
 	currentGraphicsPipeline = VK_NULL_HANDLE;
-	currentViewportWidth = (float)width;
-	currentViewportHeight = (float)height;
+	currentViewportWidth = (float)pixelw;
+	currentViewportHeight = (float)pixelh;
 	currentMsaaSamples = VK_SAMPLE_COUNT_1_BIT;
 	currentNumColorAttachments = static_cast<uint32_t>(rts.colors.size());
 
@@ -2046,9 +2058,6 @@ void Graphics::createDefaultTexture() {
 }
 
 void Graphics::cleanup() {
-	delete quadIndexBuffer;
-	quadIndexBuffer = nullptr;
-
 	cleanupSwapChain();
 
 	for (auto &cleanUpFns : cleanUpFunctions) {

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

@@ -27,6 +27,7 @@ struct RenderPassConfiguration {
 	std::vector<VkFormat> colorFormats;
 
 	struct StaticRenderPassConfiguration {
+		VkImageLayout initialColorImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 		VkSampleCountFlagBits msaaSamples = VK_SAMPLE_COUNT_1_BIT;
 		VkFormat depthFormat = VK_FORMAT_UNDEFINED;
 		bool resolve = false;

+ 2 - 2
src/modules/graphics/vulkan/Shader.cpp

@@ -652,12 +652,12 @@ void Shader::createDescriptorSetLayout() {
 			layoutBinding.binding = val.location;
 			layoutBinding.descriptorType = val.baseType == UNIFORM_SAMPLER ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
 			layoutBinding.descriptorCount = val.count;
-			layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;	// fixme: can we determine in what shader it got used?
+			layoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
 
 			bindings.push_back(layoutBinding);
 		}
 	}
-
+	
 	VkDescriptorSetLayoutBinding uniformBinding{};
 	uniformBinding.binding = uniformLocation;
 	uniformBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;

+ 8 - 6
src/modules/graphics/vulkan/Texture.cpp

@@ -50,8 +50,8 @@ bool Texture::loadVolatile() {
 	imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 	imageInfo.flags = createFlags;
 	imageInfo.imageType = Vulkan::getImageType(getTextureType());
-	imageInfo.extent.width = static_cast<uint32_t>(width);
-	imageInfo.extent.height = static_cast<uint32_t>(height);
+	imageInfo.extent.width = static_cast<uint32_t>(pixelWidth);
+	imageInfo.extent.height = static_cast<uint32_t>(pixelHeight);
 	imageInfo.extent.depth = 1;
 	imageInfo.mipLevels = static_cast<uint32_t>(getMipmapCount());
 	imageInfo.arrayLayers = static_cast<uint32_t>(layerCount);
@@ -164,8 +164,10 @@ void Texture::clear() {
 
 	VkImageSubresourceRange range{};
 	range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-	range.layerCount = static_cast<uint32_t>(layerCount);
-	range.levelCount = static_cast<uint32_t>(getMipmapCount());
+	range.baseMipLevel = 0;
+	range.levelCount = VK_REMAINING_MIP_LEVELS;
+	range.baseArrayLayer = 0;
+	range.layerCount = VK_REMAINING_ARRAY_LAYERS;
 
 	Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, 
 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
@@ -263,14 +265,14 @@ void Texture::generateMipmapsInternal() {
 
 		VkImageBlit blit{};
 		blit.srcOffsets[0] = { 0, 0, 0 };
-		blit.srcOffsets[1] = { getWidth(i - 1), getHeight(i - 1), 1 };
+		blit.srcOffsets[1] = { getPixelWidth(i - 1), getPixelHeight(i - 1), 1 };
 		blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 		blit.srcSubresource.mipLevel = i - 1;
 		blit.srcSubresource.baseArrayLayer = 0;
 		blit.srcSubresource.layerCount = static_cast<uint32_t>(layerCount);
 
 		blit.dstOffsets[0] = { 0, 0, 0 };
-		blit.dstOffsets[1] = { getWidth(i), getHeight(i), 1 };
+		blit.dstOffsets[1] = { getPixelWidth(i), getPixelHeight(i), 1 };
 		blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
 		blit.dstSubresource.mipLevel = i;
 		blit.dstSubresource.baseArrayLayer = 0;

+ 38 - 4
src/modules/graphics/vulkan/Vulkan.cpp

@@ -267,34 +267,68 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format) {
 		case PIXELFORMAT_RGB565_UNORM:   // LSB->MSB: [b: g: r]
 		case PIXELFORMAT_RGB10A2_UNORM:  // LSB->MSB: [r: g: b: a]
 		case PIXELFORMAT_RG11B10_FLOAT:  // LSB->MSB: [r: g: b]
+			throw love::Exception("unimplemented pixel format (rgba4, rgb5a1, rgb565, rgb10a2, rg11b10)");
 		case PIXELFORMAT_STENCIL8:
+			textureFormat.internalFormat = VK_FORMAT_S8_UINT;
+			textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
+			break;
 		case PIXELFORMAT_DEPTH16_UNORM:
-		case PIXELFORMAT_DEPTH24_UNORM:
-		case PIXELFORMAT_DEPTH32_FLOAT:
+			textureFormat.internalFormat = VK_FORMAT_D16_UNORM;
+			textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
+			break;
+		case PIXELFORMAT_DEPTH24_UNORM:	// ?
 		case PIXELFORMAT_DEPTH24_UNORM_STENCIL8:
+			textureFormat.internalFormat = VK_FORMAT_D24_UNORM_S8_UINT;
+			textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
+			break;
+		case PIXELFORMAT_DEPTH32_FLOAT:
+			textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT;
+			textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
+			break;
 		case PIXELFORMAT_DEPTH32_FLOAT_STENCIL8:
+			textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
+			textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;	// ?
+			break;
 		case PIXELFORMAT_DXT1_UNORM:
 		case PIXELFORMAT_DXT3_UNORM:
 		case PIXELFORMAT_DXT5_UNORM:
+			throw love::Exception("unimplemented: dxt");
 		case PIXELFORMAT_BC4_UNORM:
+			textureFormat.internalFormat = VK_FORMAT_BC4_UNORM_BLOCK;
+			break;
 		case PIXELFORMAT_BC4_SNORM:
+			textureFormat.internalFormat = VK_FORMAT_BC4_SNORM_BLOCK;
+			break;
 		case PIXELFORMAT_BC5_UNORM:
+			textureFormat.internalFormat = VK_FORMAT_BC5_UNORM_BLOCK;
+			break;
 		case PIXELFORMAT_BC5_SNORM:
+			textureFormat.internalFormat = VK_FORMAT_BC5_SNORM_BLOCK;
+			break;
 		case PIXELFORMAT_BC6H_UFLOAT:
+			textureFormat.internalFormat = VK_FORMAT_BC6H_UFLOAT_BLOCK;
+			break;
 		case PIXELFORMAT_BC6H_FLOAT:
+			textureFormat.internalFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK;
+			break;
 		case PIXELFORMAT_BC7_UNORM:
+			textureFormat.internalFormat = VK_FORMAT_BC7_UNORM_BLOCK;
+			break;
 		case PIXELFORMAT_PVR1_RGB2_UNORM:
 		case PIXELFORMAT_PVR1_RGB4_UNORM:
 		case PIXELFORMAT_PVR1_RGBA2_UNORM:
 		case PIXELFORMAT_PVR1_RGBA4_UNORM:
+			throw love::Exception("unimplemented pixel format: pvr1");
 		case PIXELFORMAT_ETC1_UNORM:
 		case PIXELFORMAT_ETC2_RGB_UNORM:
 		case PIXELFORMAT_ETC2_RGBA_UNORM:
 		case PIXELFORMAT_ETC2_RGBA1_UNORM:
+			throw love::Exception("unimplemented pixel format: etc");
 		case PIXELFORMAT_EAC_R_UNORM:
 		case PIXELFORMAT_EAC_R_SNORM:
 		case PIXELFORMAT_EAC_RG_UNORM:
 		case PIXELFORMAT_EAC_RG_SNORM:
+			throw love::Exception("unimplemented pixel format: eac");
 		case PIXELFORMAT_ASTC_4x4:
 		case PIXELFORMAT_ASTC_5x4:
 		case PIXELFORMAT_ASTC_5x5:
@@ -309,7 +343,7 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format) {
 		case PIXELFORMAT_ASTC_10x10:
 		case PIXELFORMAT_ASTC_12x10:
 		case PIXELFORMAT_ASTC_12x12:
-			throw love::Exception("unimplemented pixel format");
+			throw love::Exception("unimplemented pixel format: astc");
 		default:
 			throw love::Exception("unknown pixel format");
 	}
@@ -325,7 +359,7 @@ std::string Vulkan::getVendorName(uint32_t vendorId) {
 		return "AMD";
 	case 4318:
 		return "Nvidia";
-	case 8086:
+	case 32902:
 		return "Intel";
 	case 4203:
 		return "Apple";