Browse Source

vulkan: use vkCmdClearColorImage to clear texture

using the vulkan functionality probably leads to less bugs.
Until now it was assumed that any image was in the rgba8 format,
which is of course not correct. Clearing a texture to white or black
should now work for any format.
niki 3 years ago
parent
commit
6d7bd645fc

+ 1 - 0
src/modules/graphics/vulkan/Shader.cpp

@@ -203,6 +203,7 @@ namespace love {
 				if (currentImage != imageIndex) {
 				if (currentImage != imageIndex) {
 					currentImage = imageIndex;
 					currentImage = imageIndex;
 					count = 0;
 					count = 0;
+					streamBuffers[currentImage]->nextFrame();
 				}
 				}
 				else {
 				else {
 					if (count >= STREAMBUFFER_SIZE) {
 					if (count >= STREAMBUFFER_SIZE) {

+ 71 - 19
src/modules/graphics/vulkan/Texture.cpp

@@ -2,6 +2,8 @@
 #include "Graphics.h"
 #include "Graphics.h"
 #include "Vulkan.h"
 #include "Vulkan.h"
 
 
+#include <limits>
+
 // make vulkan::Graphics functions available
 // make vulkan::Graphics functions available
 #define vgfx ((Graphics*)gfx)
 #define vgfx ((Graphics*)gfx)
 
 
@@ -19,11 +21,7 @@ namespace love {
 
 
 				auto vulkanFormat = Vulkan::getTextureFormat(format);
 				auto vulkanFormat = Vulkan::getTextureFormat(format);
 
 
-				VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
-
-				if (isRenderTarget()) {
-					usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-				}
+				VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
 
 
 				VkImageCreateInfo imageInfo{};
 				VkImageCreateInfo imageInfo{};
 				imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
 				imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -60,22 +58,10 @@ namespace love {
 					uploadByteData(format, dataPtr, size, 0, 0, rect);
 					uploadByteData(format, dataPtr, size, 0, 0, rect);
 				} else {
 				} else {
 					if (isRenderTarget()) {
 					if (isRenderTarget()) {
-						std::vector<uint8> defaultPixels;
-						defaultPixels.reserve(width * height * 4);
-						for (size_t i = 0; i < width * height; i++) {
-							// transparent black
-							defaultPixels.push_back(0);
-							defaultPixels.push_back(0);
-							defaultPixels.push_back(0);
-							defaultPixels.push_back(255);
-						}
-						Rect rect = { 0, 0, width, height };
-						uploadByteData(PIXELFORMAT_RGBA8_UNORM, defaultPixels.data(), defaultPixels.size(), 0, 0, rect);
+						clear(false);
 					}
 					}
 					else {
 					else {
-						std::vector<uint8> defaultPixels(width * height * 4, 255);
-						Rect rect = { 0, 0, width, height };
-						uploadByteData(PIXELFORMAT_RGBA8_UNORM, defaultPixels.data(), defaultPixels.size(), 0, 0, rect);
+						clear(true);
 					}
 					}
 				}
 				}
 				createTextureImageView();
 				createTextureImageView();
@@ -153,6 +139,72 @@ namespace love {
 				}
 				}
 			}
 			}
 
 
+			void Texture::clear(bool white) {
+				auto commandBuffer = vgfx->beginSingleTimeCommands();
+
+				auto clearColor = getClearValue(white);
+
+				VkImageSubresourceRange range{};
+				range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+				range.layerCount = 1;
+				range.levelCount = 1;
+
+				vkCmdClearColorImage(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);
+
+				vgfx->endSingleTimeCommands(commandBuffer);
+			}
+
+			VkClearColorValue Texture::getClearValue(bool white) {
+				auto vulkanFormat = Vulkan::getTextureFormat(format);
+
+				VkClearColorValue clearColor{};
+				if (white) {
+					switch (vulkanFormat.internalFormatRepresentation) {
+					case FORMATREPRESENTATION_FLOAT:
+						clearColor.float32[0] = 1.0f;
+						clearColor.float32[1] = 1.0f;
+						clearColor.float32[2] = 1.0f;
+						clearColor.float32[3] = 1.0f;
+						break;
+					case FORMATREPRESENTATION_SINT:
+						clearColor.int32[0] = std::numeric_limits<int32_t>::max();
+						clearColor.int32[1] = std::numeric_limits<int32_t>::max();
+						clearColor.int32[2] = std::numeric_limits<int32_t>::max();
+						clearColor.int32[3] = std::numeric_limits<int32_t>::max();
+						break;
+					case FORMATREPRESENTATION_UINT:
+						clearColor.uint32[0] = std::numeric_limits<uint32_t>::max();
+						clearColor.uint32[1] = std::numeric_limits<uint32_t>::max();
+						clearColor.uint32[2] = std::numeric_limits<uint32_t>::max();
+						clearColor.uint32[3] = std::numeric_limits<uint32_t>::max();
+						break;
+					}
+				}
+				else {
+					switch (vulkanFormat.internalFormatRepresentation) {
+					case FORMATREPRESENTATION_FLOAT:
+						clearColor.float32[0] = 0.0f;
+						clearColor.float32[1] = 0.0f;
+						clearColor.float32[2] = 0.0f;
+						clearColor.float32[3] = 0.0f;
+						break;
+					case FORMATREPRESENTATION_SINT:
+						clearColor.int32[0] = 0;
+						clearColor.int32[1] = 0;
+						clearColor.int32[2] = 0;
+						clearColor.int32[3] = 0;
+						break;
+					case FORMATREPRESENTATION_UINT:
+						clearColor.uint32[0] = 0;
+						clearColor.uint32[1] = 0;
+						clearColor.uint32[2] = 0;
+						clearColor.uint32[3] = 0;
+						break;
+					}
+				}
+				return clearColor;
+			}
+
 			void Texture::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) {
 			void Texture::transitionImageLayout(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout) {
 				auto commandBuffer = vgfx->beginSingleTimeCommands();
 				auto commandBuffer = vgfx->beginSingleTimeCommands();
 
 

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

@@ -40,6 +40,9 @@ namespace love {
 				void copyBufferToImage(VkBuffer, VkImage, const Rect&);
 				void copyBufferToImage(VkBuffer, VkImage, const Rect&);
 				void createTextureImageView();
 				void createTextureImageView();
 				void createTextureSampler();
 				void createTextureSampler();
+				void clear(bool white);
+
+				VkClearColorValue getClearValue(bool white);
 
 
 				graphics::Graphics* gfx;
 				graphics::Graphics* gfx;
 				VkDevice device;
 				VkDevice device;

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

@@ -109,47 +109,61 @@ namespace love {
 						throw love::Exception("unknown pixel format");
 						throw love::Exception("unknown pixel format");
 					case PIXELFORMAT_NORMAL:
 					case PIXELFORMAT_NORMAL:
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_HDR:
 					case PIXELFORMAT_HDR:
 						throw love::Exception("unimplemented pixel format: hdr");
 						throw love::Exception("unimplemented pixel format: hdr");
 					case PIXELFORMAT_R8_UNORM:
 					case PIXELFORMAT_R8_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R8_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R8_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_R8_INT:
 					case PIXELFORMAT_R8_INT:
 						textureFormat.internalFormat = VK_FORMAT_R8_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R8_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_R8_UINT:
 					case PIXELFORMAT_R8_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R8_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R8_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_R16_UNORM:
 					case PIXELFORMAT_R16_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R16_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R16_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_R16_FLOAT:
 					case PIXELFORMAT_R16_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R16_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R16_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_R16_INT:
 					case PIXELFORMAT_R16_INT:
 						textureFormat.internalFormat = VK_FORMAT_R16_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R16_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_R16_UINT:
 					case PIXELFORMAT_R16_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R16_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R16_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_R32_FLOAT:
 					case PIXELFORMAT_R32_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R32_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R32_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_R32_INT:
 					case PIXELFORMAT_R32_INT:
 						textureFormat.internalFormat = VK_FORMAT_R32_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R32_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_R32_UINT:
 					case PIXELFORMAT_R32_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R32_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R32_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RG8_UNORM:
 					case PIXELFORMAT_RG8_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RG8_INT:
 					case PIXELFORMAT_RG8_INT:
 						textureFormat.internalFormat = VK_FORMAT_R8G8_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R8G8_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RG8_UINT:
 					case PIXELFORMAT_RG8_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_LA8_UNORM: // Same as RG8: but accessed as (L: L: L: A)
 					case PIXELFORMAT_LA8_UNORM: // Same as RG8: but accessed as (L: L: L: A)
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM;
@@ -157,66 +171,87 @@ namespace love {
 						textureFormat.swizzleG = VK_COMPONENT_SWIZZLE_R;
 						textureFormat.swizzleG = VK_COMPONENT_SWIZZLE_R;
 						textureFormat.swizzleB = VK_COMPONENT_SWIZZLE_R;
 						textureFormat.swizzleB = VK_COMPONENT_SWIZZLE_R;
 						textureFormat.swizzleA = VK_COMPONENT_SWIZZLE_G;
 						textureFormat.swizzleA = VK_COMPONENT_SWIZZLE_G;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RG16_UNORM:
 					case PIXELFORMAT_RG16_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R16G16_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R16G16_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RG16_FLOAT:
 					case PIXELFORMAT_RG16_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RG16_INT:
 					case PIXELFORMAT_RG16_INT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RG16_UINT:
 					case PIXELFORMAT_RG16_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RG32_FLOAT:
 					case PIXELFORMAT_RG32_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RG32_INT:
 					case PIXELFORMAT_RG32_INT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RG32_UINT:
 					case PIXELFORMAT_RG32_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA8_UNORM:
 					case PIXELFORMAT_RGBA8_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;	// fixme?
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;	// fixme?
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA8_UNORM_sRGB:
 					case PIXELFORMAT_RGBA8_UNORM_sRGB:
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_BGRA8_UNORM:
 					case PIXELFORMAT_BGRA8_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_BGRA8_UNORM_sRGB:
 					case PIXELFORMAT_BGRA8_UNORM_sRGB:
 						textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB;
 						textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA8_INT:
 					case PIXELFORMAT_RGBA8_INT:
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA8_UINT:
 					case PIXELFORMAT_RGBA8_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA16_UNORM:
 					case PIXELFORMAT_RGBA16_UNORM:
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UNORM;
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UNORM;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA16_FLOAT:
 					case PIXELFORMAT_RGBA16_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA16_INT:
 					case PIXELFORMAT_RGBA16_INT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA16_UINT:
 					case PIXELFORMAT_RGBA16_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA32_FLOAT:
 					case PIXELFORMAT_RGBA32_FLOAT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA32_INT:
 					case PIXELFORMAT_RGBA32_INT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SINT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA32_UINT:
 					case PIXELFORMAT_RGBA32_UINT:
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_UINT;
 						textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_UINT;
+						textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
 						break;
 						break;
 					case PIXELFORMAT_RGBA4_UNORM:    // LSB->MSB: [a: b: g: r]
 					case PIXELFORMAT_RGBA4_UNORM:    // LSB->MSB: [a: b: g: r]
 					case PIXELFORMAT_RGB5A1_UNORM:   // LSB->MSB: [a: b: g: r]
 					case PIXELFORMAT_RGB5A1_UNORM:   // LSB->MSB: [a: b: g: r]

+ 8 - 0
src/modules/graphics/vulkan/Vulkan.h

@@ -7,7 +7,15 @@
 namespace love {
 namespace love {
 	namespace graphics {
 	namespace graphics {
 		namespace vulkan {
 		namespace vulkan {
+			enum InternalFormatRepresentation {
+				FORMATREPRESENTATION_FLOAT,
+				FORMATREPRESENTATION_UINT,
+				FORMATREPRESENTATION_SINT,
+				FORMATREPRESENTATION_MAX_ENUM
+			};
+
 			struct TextureFormat {
 			struct TextureFormat {
+				InternalFormatRepresentation internalFormatRepresentation;
 				VkFormat internalFormat = VK_FORMAT_UNDEFINED;
 				VkFormat internalFormat = VK_FORMAT_UNDEFINED;
 
 
 				VkComponentSwizzle swizzleR = VK_COMPONENT_SWIZZLE_IDENTITY;
 				VkComponentSwizzle swizzleR = VK_COMPONENT_SWIZZLE_IDENTITY;