diff --git a/src/modules/graphics/vulkan/Shader.cpp b/src/modules/graphics/vulkan/Shader.cpp index 60e1b7b62..6d9717331 100644 --- a/src/modules/graphics/vulkan/Shader.cpp +++ b/src/modules/graphics/vulkan/Shader.cpp @@ -203,6 +203,7 @@ namespace love { if (currentImage != imageIndex) { currentImage = imageIndex; count = 0; + streamBuffers[currentImage]->nextFrame(); } else { if (count >= STREAMBUFFER_SIZE) { diff --git a/src/modules/graphics/vulkan/Texture.cpp b/src/modules/graphics/vulkan/Texture.cpp index 5cc07d3df..21d5b71d3 100644 --- a/src/modules/graphics/vulkan/Texture.cpp +++ b/src/modules/graphics/vulkan/Texture.cpp @@ -2,6 +2,8 @@ #include "Graphics.h" #include "Vulkan.h" +#include + // make vulkan::Graphics functions available #define vgfx ((Graphics*)gfx) @@ -19,11 +21,7 @@ namespace love { 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{}; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; @@ -60,22 +58,10 @@ namespace love { uploadByteData(format, dataPtr, size, 0, 0, rect); } else { if (isRenderTarget()) { - std::vector 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 { - std::vector 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(); @@ -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::max(); + clearColor.int32[1] = std::numeric_limits::max(); + clearColor.int32[2] = std::numeric_limits::max(); + clearColor.int32[3] = std::numeric_limits::max(); + break; + case FORMATREPRESENTATION_UINT: + clearColor.uint32[0] = std::numeric_limits::max(); + clearColor.uint32[1] = std::numeric_limits::max(); + clearColor.uint32[2] = std::numeric_limits::max(); + clearColor.uint32[3] = std::numeric_limits::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) { auto commandBuffer = vgfx->beginSingleTimeCommands(); diff --git a/src/modules/graphics/vulkan/Texture.h b/src/modules/graphics/vulkan/Texture.h index e123f3271..df0b1900d 100644 --- a/src/modules/graphics/vulkan/Texture.h +++ b/src/modules/graphics/vulkan/Texture.h @@ -40,6 +40,9 @@ namespace love { void copyBufferToImage(VkBuffer, VkImage, const Rect&); void createTextureImageView(); void createTextureSampler(); + void clear(bool white); + + VkClearColorValue getClearValue(bool white); graphics::Graphics* gfx; VkDevice device; diff --git a/src/modules/graphics/vulkan/Vulkan.cpp b/src/modules/graphics/vulkan/Vulkan.cpp index 66fdfe920..c10b2bdaa 100644 --- a/src/modules/graphics/vulkan/Vulkan.cpp +++ b/src/modules/graphics/vulkan/Vulkan.cpp @@ -109,47 +109,61 @@ namespace love { throw love::Exception("unknown pixel format"); case PIXELFORMAT_NORMAL: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_HDR: throw love::Exception("unimplemented pixel format: hdr"); case PIXELFORMAT_R8_UNORM: textureFormat.internalFormat = VK_FORMAT_R8_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_R8_INT: textureFormat.internalFormat = VK_FORMAT_R8_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_R8_UINT: textureFormat.internalFormat = VK_FORMAT_R8_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_R16_UNORM: textureFormat.internalFormat = VK_FORMAT_R16_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_R16_FLOAT: textureFormat.internalFormat = VK_FORMAT_R16_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_R16_INT: textureFormat.internalFormat = VK_FORMAT_R16_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_R16_UINT: textureFormat.internalFormat = VK_FORMAT_R16_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_R32_FLOAT: textureFormat.internalFormat = VK_FORMAT_R32_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_R32_INT: textureFormat.internalFormat = VK_FORMAT_R32_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_R32_UINT: textureFormat.internalFormat = VK_FORMAT_R32_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RG8_UNORM: textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RG8_INT: textureFormat.internalFormat = VK_FORMAT_R8G8_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RG8_UINT: textureFormat.internalFormat = VK_FORMAT_R8G8_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_LA8_UNORM: // Same as RG8: but accessed as (L: L: L: A) textureFormat.internalFormat = VK_FORMAT_R8G8_UNORM; @@ -157,66 +171,87 @@ namespace love { textureFormat.swizzleG = VK_COMPONENT_SWIZZLE_R; textureFormat.swizzleB = VK_COMPONENT_SWIZZLE_R; textureFormat.swizzleA = VK_COMPONENT_SWIZZLE_G; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RG16_UNORM: textureFormat.internalFormat = VK_FORMAT_R16G16_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RG16_FLOAT: textureFormat.internalFormat = VK_FORMAT_R16G16_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RG16_INT: textureFormat.internalFormat = VK_FORMAT_R16G16_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RG16_UINT: textureFormat.internalFormat = VK_FORMAT_R16G16_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RG32_FLOAT: textureFormat.internalFormat = VK_FORMAT_R32G32_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RG32_INT: textureFormat.internalFormat = VK_FORMAT_R32G32_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RG32_UINT: textureFormat.internalFormat = VK_FORMAT_R32G32_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RGBA8_UNORM: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB; // fixme? + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RGBA8_UNORM_sRGB: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_BGRA8_UNORM: textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_BGRA8_UNORM_sRGB: textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RGBA8_INT: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RGBA8_UINT: textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RGBA16_UNORM: textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UNORM; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RGBA16_FLOAT: textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RGBA16_INT: textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RGBA16_UINT: textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RGBA32_FLOAT: textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SFLOAT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_FLOAT; break; case PIXELFORMAT_RGBA32_INT: textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_SINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_SINT; break; case PIXELFORMAT_RGBA32_UINT: textureFormat.internalFormat = VK_FORMAT_R32G32B32A32_UINT; + textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT; break; case PIXELFORMAT_RGBA4_UNORM: // LSB->MSB: [a: b: g: r] case PIXELFORMAT_RGB5A1_UNORM: // LSB->MSB: [a: b: g: r] diff --git a/src/modules/graphics/vulkan/Vulkan.h b/src/modules/graphics/vulkan/Vulkan.h index a4b8f010b..c8c438f74 100644 --- a/src/modules/graphics/vulkan/Vulkan.h +++ b/src/modules/graphics/vulkan/Vulkan.h @@ -7,7 +7,15 @@ namespace love { namespace graphics { namespace vulkan { + enum InternalFormatRepresentation { + FORMATREPRESENTATION_FLOAT, + FORMATREPRESENTATION_UINT, + FORMATREPRESENTATION_SINT, + FORMATREPRESENTATION_MAX_ENUM + }; + struct TextureFormat { + InternalFormatRepresentation internalFormatRepresentation; VkFormat internalFormat = VK_FORMAT_UNDEFINED; VkComponentSwizzle swizzleR = VK_COMPONENT_SWIZZLE_IDENTITY;