Browse Source

vulkan: implement compressed textures

niki 2 years ago
parent
commit
e128f3453e

+ 1 - 1
src/modules/graphics/vulkan/Buffer.cpp

@@ -58,7 +58,7 @@ bool Buffer::loadVolatile()
 	if (result != VK_SUCCESS)
 		throw love::Exception("failed to create buffer");
 
-	if (usageFlags & BUFFERUSAGE_TEXEL)
+	if (usageFlags & BUFFERUSAGEFLAG_TEXEL)
 	{
 		VkBufferViewCreateInfo bufferViewInfo{};
 		bufferViewInfo.buffer = buffer;

+ 84 - 14
src/modules/graphics/vulkan/Graphics.cpp

@@ -184,7 +184,7 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
 		1, &rect);
 }
 
-void Graphics::discard(const std::vector<bool>& colorbuffers, bool depthstencil)
+void Graphics::discard(const std::vector<bool> &colorbuffers, bool depthstencil)
 {
 	if (renderPassState.active)
 		endRenderPass();
@@ -228,7 +228,7 @@ void Graphics::discard(const std::vector<bool>& colorbuffers, bool depthstencil)
 	startRenderPass();
 }
 
-void Graphics::submitGpuCommands(bool present, void* screenshotCallbackData)
+void Graphics::submitGpuCommands(bool present, void *screenshotCallbackData)
 {
 	flushBatchedDraws();
 
@@ -409,7 +409,7 @@ void Graphics::present(void *screenshotCallbackdata)
 
 	deprecations.draw(this);
 
-	submitGpuCommands(true);
+	submitGpuCommands(true, screenshotCallbackdata);
 
 	VkPresentInfoKHR presentInfo{};
 	presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@@ -538,7 +538,7 @@ void Graphics::initCapabilities()
 	capabilities.features[FEATURE_GLSL3] = true;
 	capabilities.features[FEATURE_GLSL4] = true;
 	capabilities.features[FEATURE_INSTANCING] = true;
-	capabilities.features[FEATURE_TEXEL_BUFFER] = false;
+	capabilities.features[FEATURE_TEXEL_BUFFER] = true;
 	capabilities.features[FEATURE_INDEX_BUFFER_32BIT] = true;
 	capabilities.features[FEATURE_COPY_BUFFER] = true;
 	capabilities.features[FEATURE_COPY_BUFFER_TO_TEXTURE] = true;
@@ -554,13 +554,13 @@ void Graphics::initCapabilities()
 	capabilities.limits[LIMIT_TEXTURE_LAYERS] = properties.limits.maxImageArrayLayers;
 	capabilities.limits[LIMIT_VOLUME_TEXTURE_SIZE] = properties.limits.maxImageDimension3D;
 	capabilities.limits[LIMIT_CUBE_TEXTURE_SIZE] = properties.limits.maxImageDimensionCube;
-	capabilities.limits[LIMIT_TEXEL_BUFFER_SIZE] = properties.limits.maxTexelBufferElements;	// ?
-	capabilities.limits[LIMIT_SHADER_STORAGE_BUFFER_SIZE] = properties.limits.maxStorageBufferRange;	// ?
-	capabilities.limits[LIMIT_THREADGROUPS_X] = properties.limits.maxComputeWorkGroupSize[0];	// this is correct?
+	capabilities.limits[LIMIT_TEXEL_BUFFER_SIZE] = properties.limits.maxTexelBufferElements;
+	capabilities.limits[LIMIT_SHADER_STORAGE_BUFFER_SIZE] = properties.limits.maxStorageBufferRange;
+	capabilities.limits[LIMIT_THREADGROUPS_X] = properties.limits.maxComputeWorkGroupSize[0];
 	capabilities.limits[LIMIT_THREADGROUPS_Y] = properties.limits.maxComputeWorkGroupSize[1];
 	capabilities.limits[LIMIT_THREADGROUPS_Z] = properties.limits.maxComputeWorkGroupSize[2];
 	capabilities.limits[LIMIT_RENDER_TARGETS] = properties.limits.maxColorAttachments;
-	capabilities.limits[LIMIT_TEXTURE_MSAA] = 1;	// todo
+	capabilities.limits[LIMIT_TEXTURE_MSAA] = static_cast<double>(getMsaaCount(64));
 	capabilities.limits[LIMIT_ANISOTROPY] = properties.limits.maxSamplerAnisotropy;
 	static_assert(LIMIT_MAX_ENUM == 13, "Graphics::initCapabilities must be updated when adding a new system limit!");
 
@@ -892,6 +892,75 @@ PixelFormat Graphics::getSizedFormat(PixelFormat format, bool rendertarget, bool
 
 bool Graphics::isPixelFormatSupported(PixelFormat format, uint32 usage, bool sRGB)
 {
+	(void)sRGB;	// fixme: sRGB
+
+	auto vulkanFormat = Vulkan::getTextureFormat(format);
+
+	VkFormatProperties formatProperties;
+	vkGetPhysicalDeviceFormatProperties(physicalDevice, vulkanFormat.internalFormat, &formatProperties);
+
+	VkFormatFeatureFlags featureFlags;
+	VkImageTiling tiling;
+	VkImageUsageFlags usageFlags = 0;
+
+	if (usage & PIXELFORMATUSAGEFLAGS_LINEAR)
+	{
+		tiling = VK_IMAGE_TILING_LINEAR;
+		featureFlags = formatProperties.linearTilingFeatures;
+	}
+	else
+	{
+		tiling = VK_IMAGE_TILING_OPTIMAL;
+		featureFlags = formatProperties.optimalTilingFeatures;
+	}
+
+	if (!featureFlags)
+		return false;
+
+	if (usage & PIXELFORMATUSAGEFLAGS_SAMPLE)
+	{
+		usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
+		if (!(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
+			return false;
+	}
+
+	if (usage & PIXELFORMATUSAGEFLAGS_RENDERTARGET)
+	{
+		if (isPixelFormatDepth(format) || isPixelFormatDepthStencil(format))
+		{
+			usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+			if (!(featureFlags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
+				return false;
+		}
+		else
+		{
+			usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+			if (!(featureFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
+				return false;
+		}
+	}
+
+	if (usage & PIXELFORMATUSAGEFLAGS_BLEND)
+		if (!(featureFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT))
+			return false;
+
+	if (usage & PIXELFORMATUSAGEFLAGS_COMPUTEWRITE)
+	{
+		usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
+		if (!(featureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
+			return false;
+	}
+
+	if (usage & PIXELFORMATUSAGEFLAGS_MSAA)
+	{
+		VkImageFormatProperties properties;
+
+		vkGetPhysicalDeviceImageFormatProperties(physicalDevice, vulkanFormat.internalFormat, VK_IMAGE_TYPE_2D, tiling, usageFlags, 0, &properties);
+
+		if (static_cast<uint32_t>(properties.sampleCounts) == 1)
+			return false;
+	}
+
 	return true;
 }
 
@@ -1175,7 +1244,7 @@ static void checkOptionalInstanceExtensions(OptionalInstanceExtensions &ext)
 
 	vkEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data());
 
-	for (const auto& extension : extensions)
+	for (const auto &extension : extensions)
 	{
 #ifdef VK_KHR_get_physical_device_properties2
 		if (strcmp(extension.extensionName, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) == 0)
@@ -1404,7 +1473,7 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
 	std::vector<VkExtensionProperties> availableExtensions(extensionCount);
 	vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());
 
-	for (const auto& extension : availableExtensions)
+	for (const auto &extension : availableExtensions)
 	{
 #ifdef VK_EXT_extended_dynamic_state
 		if (strcmp(extension.extensionName, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) == 0)
@@ -1720,7 +1789,7 @@ void Graphics::createSwapChain()
 
 VkSurfaceFormatKHR Graphics::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats)
 {
-	for (const auto& availableFormat : availableFormats)
+	for (const auto &availableFormat : availableFormats)
 		// fixme: what if this format and colorspace is not available?
 		if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
 			return availableFormat;
@@ -1735,7 +1804,8 @@ VkPresentModeKHR Graphics::chooseSwapPresentMode(const std::vector<VkPresentMode
 	const auto begin = availablePresentModes.begin();
 	const auto end = availablePresentModes.end();
 
-	switch (vsync) {
+	switch (vsync)
+	{
 	case -1:
 		if (std::find(begin, end, VK_PRESENT_MODE_FIFO_RELAXED_KHR) != end)
 			return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
@@ -2097,7 +2167,7 @@ void Graphics::createVulkanVertexFormat(
 
 	uint8_t highestBufferBinding = 0;
 
-	// change to loop like in opengl implementation ?
+	// fixme: change to loop like in opengl implementation ?
 	for (uint32_t i = 0; i < VertexAttributes::MAX; i++)
 	{
 		uint32 bit = 1u << i;
@@ -2815,7 +2885,7 @@ void Graphics::cleanup()
 
 void Graphics::cleanupSwapChain()
 {
-	for (const auto& readbackBuffer : screenshotReadbackBuffers)
+	for (const auto &readbackBuffer : screenshotReadbackBuffers)
 	{
 		vmaDestroyBuffer(vmaAllocator, readbackBuffer.buffer, readbackBuffer.allocation);
 		vmaDestroyImage(vmaAllocator, readbackBuffer.image, readbackBuffer.imageAllocation);

+ 28 - 21
src/modules/graphics/vulkan/Texture.cpp

@@ -34,9 +34,12 @@ bool Texture::loadVolatile()
 		VK_IMAGE_USAGE_TRANSFER_DST_BIT;
 
 	if (readable)
-		usageFlags |= 
-			VK_IMAGE_USAGE_SAMPLED_BIT |
-			VK_IMAGE_USAGE_STORAGE_BIT;
+	{
+		usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
+
+		if (!isPixelFormatCompressed(format))
+			usageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
+	}
 
 	if (isPixelFormatDepthStencil(format) || isPixelFormatDepth(format))
 		usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
@@ -66,9 +69,12 @@ bool Texture::loadVolatile()
 	imageInfo.extent.height = static_cast<uint32_t>(pixelHeight);
 	imageInfo.extent.depth = static_cast<uint32_t>(depth);
 	imageInfo.arrayLayers = static_cast<uint32_t>(layerCount);
-	imageInfo.mipLevels = static_cast<uint32_t>(getMipmapCount());
+	imageInfo.mipLevels = static_cast<uint32_t>(mipmapCount);
 	imageInfo.format = vulkanFormat.internalFormat;
-	imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+	if (isPixelFormatCompressed(format))
+		imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+	else
+		imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
 	imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
 	imageInfo.usage = usageFlags;
 	imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@@ -100,26 +106,26 @@ bool Texture::loadVolatile()
 	if (hasdata)
 		for (int mip = 0; mip < getMipmapCount(); mip++)
 		{
-			// fixme: deal with compressed images.
-
 			int sliceCount;
 			if (texType == TEXTURE_CUBE)
 				sliceCount = 6;
 			else
 				sliceCount = slices.getSliceCount();
+
 			for (int slice = 0; slice < sliceCount; slice++)
 			{
-				auto *id = slices.get(slice, mip);
+				auto* id = slices.get(slice, mip);
 				if (id != nullptr)
 					uploadImageData(id, mip, slice, 0, 0);
 			}
 		}
 	else
 		clear();
+
 	createTextureImageView();
 	textureSampler = vgfx->getCachedSampler(samplerState);
 
-	if (slices.getMipmapCount() <= 1 && getMipmapsMode() != MIPMAPS_NONE)
+	if (mipmapCount > 1 && getMipmapsMode() != MIPMAPS_NONE)
 		generateMipmaps();
 
 	if (renderTarget)
@@ -436,12 +442,15 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
 	region.bufferRowLength = 0;
 	region.bufferImageHeight = 0;
 
-	region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
-	region.imageSubresource.mipLevel = level;
+	uint32_t baseLayer;
 	if (getTextureType() == TEXTURE_VOLUME)
-		region.imageSubresource.baseArrayLayer = 0;
+		baseLayer = 0;
 	else
-		region.imageSubresource.baseArrayLayer = slice;
+		baseLayer = slice;
+
+	region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+	region.imageSubresource.mipLevel = level;
+	region.imageSubresource.baseArrayLayer = baseLayer;
 	region.imageSubresource.layerCount = 1;
 
 	region.imageOffset = { r.x, r.y, 0 };
@@ -455,13 +464,11 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
 
 	auto commandBuffer = vgfx->getCommandBufferForDataTransfer();
 
-
 	if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
 	{
 		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, 
-			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
-			level, 1, slice, 1);
-
+			imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 
+			level, 1, baseLayer, 1);
 
 		vkCmdCopyBufferToImage(
 			commandBuffer,
@@ -473,8 +480,8 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s
 		);
 
 		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage,
-			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
-			level, 1, slice, 1);
+			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageLayout,
+			level, 1, baseLayer, 1);
 	}
 	else
 		vkCmdCopyBufferToImage(
@@ -542,11 +549,11 @@ void Texture::copyToBuffer(graphics::Buffer *dest, int slice, int mipmap, const
 
 	if (imageLayout != VK_IMAGE_LAYOUT_GENERAL)
 	{
-		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, imageLayout, 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_SHADER_READ_ONLY_OPTIMAL);
+		Vulkan::cmdTransitionImageLayout(commandBuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, imageLayout);
 	}
 	else
 		vkCmdCopyImageToBuffer(commandBuffer, textureImage, VK_IMAGE_LAYOUT_GENERAL, (VkBuffer)dest->getHandle(), 1, &region);

+ 299 - 232
src/modules/graphics/vulkan/Vulkan.cpp

@@ -127,238 +127,305 @@ TextureFormat Vulkan::getTextureFormat(PixelFormat format)
 
 	switch (format)
 	{
-		case PIXELFORMAT_UNKNOWN:
-			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;
-			textureFormat.swizzleR = VK_COMPONENT_SWIZZLE_R;
-			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_UNORM;
-			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]
-		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:
-			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:
-		case PIXELFORMAT_ASTC_6x5:
-		case PIXELFORMAT_ASTC_6x6:
-		case PIXELFORMAT_ASTC_8x5:
-		case PIXELFORMAT_ASTC_8x6:
-		case PIXELFORMAT_ASTC_8x8:
-		case PIXELFORMAT_ASTC_10x5:
-		case PIXELFORMAT_ASTC_10x6:
-		case PIXELFORMAT_ASTC_10x8:
-		case PIXELFORMAT_ASTC_10x10:
-		case PIXELFORMAT_ASTC_12x10:
-		case PIXELFORMAT_ASTC_12x12:
-			throw love::Exception("unimplemented pixel format: astc");
-		default:
-			throw love::Exception("unknown pixel format");
+	case PIXELFORMAT_UNKNOWN:
+		throw love::Exception("unknown pixel format");
+	case PIXELFORMAT_NORMAL:
+		textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
+		break;
+	case PIXELFORMAT_HDR:
+		throw love::Exception("unimplemented pixel format: hdr");
+	case PIXELFORMAT_R8_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_R8_UNORM;
+		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;
+		break;
+	case PIXELFORMAT_R16_FLOAT:
+		textureFormat.internalFormat = VK_FORMAT_R16_SFLOAT;
+		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;
+		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;
+		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;
+		textureFormat.swizzleR = VK_COMPONENT_SWIZZLE_R;
+		textureFormat.swizzleG = VK_COMPONENT_SWIZZLE_R;
+		textureFormat.swizzleB = VK_COMPONENT_SWIZZLE_R;
+		textureFormat.swizzleA = VK_COMPONENT_SWIZZLE_G;
+		break;
+	case PIXELFORMAT_RG16_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_R16G16_UNORM;
+		break;
+	case PIXELFORMAT_RG16_FLOAT:
+		textureFormat.internalFormat = VK_FORMAT_R16G16_SFLOAT;
+		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;
+		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_UNORM;
+		break;
+	case PIXELFORMAT_RGBA8_UNORM_sRGB:
+		textureFormat.internalFormat = VK_FORMAT_R8G8B8A8_SRGB;
+		break;
+	case PIXELFORMAT_BGRA8_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_UNORM;
+		break;
+	case PIXELFORMAT_BGRA8_UNORM_sRGB:
+		textureFormat.internalFormat = VK_FORMAT_B8G8R8A8_SRGB;
+		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;
+		break;
+	case PIXELFORMAT_RGBA16_FLOAT:
+		textureFormat.internalFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+		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;
+		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]
+		textureFormat.internalFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16;
+		break;
+	case PIXELFORMAT_RGB5A1_UNORM:   // LSB->MSB: [a: b: g: r]
+		textureFormat.internalFormat = VK_FORMAT_R5G5B5A1_UNORM_PACK16;
+		break;
+	case PIXELFORMAT_RGB565_UNORM:   // LSB->MSB: [b: g: r]
+		textureFormat.internalFormat = VK_FORMAT_R5G6B5_UNORM_PACK16;
+		break;
+	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 (rgb10a2, rg11b10)");
+	case PIXELFORMAT_STENCIL8:
+		textureFormat.internalFormat = VK_FORMAT_S8_UINT;
+		textureFormat.internalFormatRepresentation = FORMATREPRESENTATION_UINT;
+		break;
+	case PIXELFORMAT_DEPTH16_UNORM:
+		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;
+		break;
+	case PIXELFORMAT_DEPTH32_FLOAT_STENCIL8:
+		textureFormat.internalFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
+		break;
+	case PIXELFORMAT_DXT1_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_DXT3_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_BC2_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_DXT5_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_BC3_UNORM_BLOCK;
+		break;
+	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:
+		textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
+		break;
+	case PIXELFORMAT_PVR1_RGB4_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
+		break;
+	case PIXELFORMAT_PVR1_RGBA2_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
+		break;
+	case PIXELFORMAT_PVR1_RGBA4_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG;
+		break;
+	case PIXELFORMAT_ETC1_UNORM:
+		throw love::Exception("unimplemented pixel format: etc1");
+	case PIXELFORMAT_ETC2_RGB_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_ETC2_RGBA_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_ETC2_RGBA1_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_EAC_R_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_EAC_R11_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_EAC_R_SNORM:
+		textureFormat.internalFormat = VK_FORMAT_EAC_R11_SNORM_BLOCK;
+		break;
+	case PIXELFORMAT_EAC_RG_UNORM:
+		textureFormat.internalFormat = VK_FORMAT_EAC_R11G11_UNORM_BLOCK;
+		break;
+	case PIXELFORMAT_EAC_RG_SNORM:
+		textureFormat.internalFormat = VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
+		break;
+	case PIXELFORMAT_ASTC_4x4:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_5x4:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_5x5:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_6x5:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_6x6:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_8x5:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_8x6:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_8x8:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_10x5:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_10x6:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_10x8:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_10x10:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_12x10:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	case PIXELFORMAT_ASTC_12x12:
+#ifdef VK_EXT_texture_compression_astc_hdr
+		textureFormat.internalFormat = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT;
+#endif
+		break;
+	default:
+		throw love::Exception("unknown pixel format");
 	}
 
 	return textureFormat;

+ 2 - 2
src/modules/graphics/vulkan/Vulkan.h

@@ -20,7 +20,7 @@ enum InternalFormatRepresentation
 
 struct TextureFormat
 {
-	InternalFormatRepresentation internalFormatRepresentation;
+	InternalFormatRepresentation internalFormatRepresentation = FORMATREPRESENTATION_FLOAT;
 	VkFormat internalFormat = VK_FORMAT_UNDEFINED;
 
 	VkComponentSwizzle swizzleR = VK_COMPONENT_SWIZZLE_IDENTITY;
@@ -63,7 +63,7 @@ public:
 
 	static void cmdTransitionImageLayout(
 		VkCommandBuffer, VkImage, VkImageLayout oldLayout, VkImageLayout newLayout,
-		uint32_t baseLevel = 0, uint32_t levelCount = 1, uint32_t baseLayer = 0, uint32_t layerCount = 1);
+		uint32_t baseLevel = 0, uint32_t levelCount = VK_REMAINING_MIP_LEVELS, uint32_t baseLayer = 0, uint32_t layerCount = VK_REMAINING_ARRAY_LAYERS);
 };
 
 } // vulkan