Browse Source

Remove the texture format workaround support. Some mobile optimizations

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
73ba9292ac

+ 4 - 1
AnKi/Gr/Common.h

@@ -161,10 +161,13 @@ public:
 
 	/// Supports min/max texture filtering.
 	Bool m_samplingFilterMinMax = false;
+
+	/// Supports or not 24bit, 48bit or 96bit texture formats.
+	Bool m_unalignedBbpTextureFormats = false;
 };
 ANKI_END_PACKED_STRUCT
 static_assert(sizeof(GpuDeviceCapabilities)
-				  == sizeof(PtrSize) * 4 + sizeof(U32) * 5 + sizeof(U8) * 3 + sizeof(Bool) * 4,
+				  == sizeof(PtrSize) * 4 + sizeof(U32) * 5 + sizeof(U8) * 3 + sizeof(Bool) * 5,
 			  "Should be packed");
 
 /// The type of the allocator for heap allocations

+ 22 - 104
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -659,114 +659,32 @@ void CommandBufferImpl::copyBufferToTextureViewInternal(BufferPtr buff, PtrSize
 	ANKI_ASSERT(width && height);
 	const U32 depth = (is3D) ? (tex.getDepth() >> surf.m_level) : 1u;
 
-	if(!tex.m_workarounds)
+	if(!is3D)
 	{
-		if(!is3D)
-		{
-			ANKI_ASSERT(range == computeSurfaceSize(width, height, tex.getFormat()));
-		}
-		else
-		{
-			ANKI_ASSERT(range == computeVolumeSize(width, height, depth, tex.getFormat()));
-		}
-
-		// Copy
-		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = aspect;
-		region.imageSubresource.baseArrayLayer = (is3D) ? tex.computeVkArrayLayer(vol) : tex.computeVkArrayLayer(surf);
-		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = surf.m_level;
-		region.imageOffset = {0, 0, 0};
-		region.imageExtent.width = width;
-		region.imageExtent.height = height;
-		region.imageExtent.depth = depth;
-		region.bufferOffset = offset;
-		region.bufferImageHeight = 0;
-		region.bufferRowLength = 0;
-
-		ANKI_CMD(vkCmdCopyBufferToImage(m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), tex.m_imageHandle,
-										layout, 1, &region),
-				 ANY_OTHER_COMMAND);
-	}
-	else if(!!(tex.m_workarounds & TextureImplWorkaround::R8G8B8_TO_R8G8B8A8))
-	{
-		// Create a new shadow buffer
-		const PtrSize shadowSize = (is3D) ? computeVolumeSize(width, height, depth, Format::R8G8B8A8_UNORM)
-										  : computeSurfaceSize(width, height, Format::R8G8B8A8_UNORM);
-		BufferPtr shadow = getManager().newBuffer(
-			BufferInitInfo(shadowSize, BufferUsageBit::ALL_TRANSFER, BufferMapAccessBit::NONE, "Workaround"));
-		const VkBuffer shadowHandle = static_cast<const BufferImpl&>(*shadow).getHandle();
-		m_microCmdb->pushObjectRef(shadow);
-
-		// Copy to shadow buffer in batches. If the number of pixels is high and we do a single vkCmdCopyBuffer we will
-		// need many regions. That allocation will be huge so do the copies in batches.
-		const U32 regionCount = width * height * depth;
-		const U32 REGIONS_PER_CMD_COPY_BUFFER = 32;
-		const U32 cmdCopyBufferCount = (regionCount + REGIONS_PER_CMD_COPY_BUFFER - 1) / REGIONS_PER_CMD_COPY_BUFFER;
-		for(U32 cmdCopyBuffer = 0; cmdCopyBuffer < cmdCopyBufferCount; ++cmdCopyBuffer)
-		{
-			const U32 beginRegion = cmdCopyBuffer * REGIONS_PER_CMD_COPY_BUFFER;
-			const U32 endRegion = min(regionCount, (cmdCopyBuffer + 1) * REGIONS_PER_CMD_COPY_BUFFER);
-			ANKI_ASSERT(beginRegion < regionCount);
-			ANKI_ASSERT(endRegion <= regionCount);
-
-			const U32 crntRegionCount = endRegion - beginRegion;
-			DynamicArrayAuto<VkBufferCopy> regions(m_alloc);
-			regions.create(crntRegionCount);
-
-			// Populate regions
-			U32 count = 0;
-			for(U32 regionIdx = beginRegion; regionIdx < endRegion; ++regionIdx)
-			{
-				U32 x, y, d;
-				unflatten3dArrayIndex(width, height, depth, regionIdx, x, y, d);
-
-				VkBufferCopy& c = regions[count++];
-
-				if(is3D)
-				{
-					c.srcOffset = (d * height * width + y * width + x) * 3 + offset;
-					c.dstOffset = (d * height * width + y * width + x) * 4 + 0;
-				}
-				else
-				{
-					c.srcOffset = (y * width + x) * 3 + offset;
-					c.dstOffset = (y * width + x) * 4 + 0;
-				}
-				c.size = 3;
-			}
-
-			// Do the copy to the shadow buffer
-			ANKI_CMD(vkCmdCopyBuffer(m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), shadowHandle,
-									 regions.getSize(), &regions[0]),
-					 ANY_OTHER_COMMAND);
-		}
-
-		// Set barrier
-		setBufferBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
-						 VK_ACCESS_TRANSFER_READ_BIT, 0, shadowSize, shadowHandle);
-
-		// Do the copy to the image
-		VkBufferImageCopy region;
-		region.imageSubresource.aspectMask = aspect;
-		region.imageSubresource.baseArrayLayer = (is3D) ? tex.computeVkArrayLayer(vol) : tex.computeVkArrayLayer(surf);
-		region.imageSubresource.layerCount = 1;
-		region.imageSubresource.mipLevel = surf.m_level;
-		region.imageOffset = {0, 0, 0};
-		region.imageExtent.width = width;
-		region.imageExtent.height = height;
-		region.imageExtent.depth = depth;
-		region.bufferOffset = 0;
-		region.bufferImageHeight = 0;
-		region.bufferRowLength = 0;
-
-		ANKI_CMD(vkCmdCopyBufferToImage(m_handle, shadowHandle, tex.m_imageHandle, layout, 1, &region),
-				 ANY_OTHER_COMMAND);
+		ANKI_ASSERT(range == computeSurfaceSize(width, height, tex.getFormat()));
 	}
 	else
 	{
-		ANKI_ASSERT(0);
-	}
+		ANKI_ASSERT(range == computeVolumeSize(width, height, depth, tex.getFormat()));
+	}
+
+	// Copy
+	VkBufferImageCopy region;
+	region.imageSubresource.aspectMask = aspect;
+	region.imageSubresource.baseArrayLayer = (is3D) ? tex.computeVkArrayLayer(vol) : tex.computeVkArrayLayer(surf);
+	region.imageSubresource.layerCount = 1;
+	region.imageSubresource.mipLevel = surf.m_level;
+	region.imageOffset = {0, 0, 0};
+	region.imageExtent.width = width;
+	region.imageExtent.height = height;
+	region.imageExtent.depth = depth;
+	region.bufferOffset = offset;
+	region.bufferImageHeight = 0;
+	region.bufferRowLength = 0;
+
+	ANKI_CMD(vkCmdCopyBufferToImage(m_handle, static_cast<const BufferImpl&>(*buff).getHandle(), tex.m_imageHandle,
+									layout, 1, &region),
+			 ANY_OTHER_COMMAND);
 
 	m_microCmdb->pushObjectRef(texView);
 	m_microCmdb->pushObjectRef(buff);

+ 16 - 41
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -153,63 +153,38 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	m_occlusionQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_OCCLUSION);
 	m_timestampQueryFactory.init(getAllocator(), m_device, VK_QUERY_TYPE_TIMESTAMP);
 
-	// Set m_r8g8b8ImagesSupported
+	// See if analigned formats are supported
 	{
+		m_capabilities.m_unalignedBbpTextureFormats = true;
+
 		VkImageFormatProperties props = {};
-		const VkResult res = vkGetPhysicalDeviceImageFormatProperties(
+		VkResult res = vkGetPhysicalDeviceImageFormatProperties(
 			m_physicalDevice, VK_FORMAT_R8G8B8_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
 			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
-
 		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
 		{
-			ANKI_VK_LOGI("R8G8B8 Images are not supported. Will workaround this");
-			m_r8g8b8ImagesSupported = false;
-		}
-		else
-		{
-			ANKI_ASSERT(res == VK_SUCCESS);
-			ANKI_VK_LOGI("R8G8B8 Images are supported");
-			m_r8g8b8ImagesSupported = true;
+			m_capabilities.m_unalignedBbpTextureFormats = false;
 		}
-	}
-
-	// Set m_s8ImagesSupported
-	{
-		VkImageFormatProperties props = {};
-		const VkResult res = vkGetPhysicalDeviceImageFormatProperties(
-			m_physicalDevice, VK_FORMAT_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
-			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props);
 
+		res = vkGetPhysicalDeviceImageFormatProperties(
+			m_physicalDevice, VK_FORMAT_R16G16B16_UNORM, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
 		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
 		{
-			ANKI_VK_LOGI("S8 Images are not supported. Will workaround this");
-			m_s8ImagesSupported = false;
+			m_capabilities.m_unalignedBbpTextureFormats = false;
 		}
-		else
-		{
-			ANKI_ASSERT(res == VK_SUCCESS);
-			ANKI_VK_LOGI("S8 Images are supported");
-			m_s8ImagesSupported = true;
-		}
-	}
-
-	// Set m_d24S8ImagesSupported
-	{
-		VkImageFormatProperties props = {};
-		VkResult res = vkGetPhysicalDeviceImageFormatProperties(
-			m_physicalDevice, VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
-			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0, &props);
 
+		res = vkGetPhysicalDeviceImageFormatProperties(
+			m_physicalDevice, VK_FORMAT_R32G32B32_SFLOAT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
+			VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &props);
 		if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
 		{
-			ANKI_VK_LOGI("D24S8 Images are not supported. Will workaround this");
-			m_d24S8ImagesSupported = false;
+			m_capabilities.m_unalignedBbpTextureFormats = false;
 		}
-		else
+
+		if(!m_capabilities.m_unalignedBbpTextureFormats)
 		{
-			ANKI_ASSERT(res == VK_SUCCESS);
-			ANKI_VK_LOGI("D24S8 Images are supported");
-			m_d24S8ImagesSupported = true;
+			ANKI_VK_LOGI("R8G8B8, R16G16B16 and R32G32B32 image formats are not supported");
 		}
 	}
 

+ 0 - 19
AnKi/Gr/Vulkan/GrManagerImpl.h

@@ -131,21 +131,6 @@ public:
 		return m_timestampQueryFactory;
 	}
 
-	Bool getR8g8b8ImagesSupported() const
-	{
-		return m_r8g8b8ImagesSupported;
-	}
-
-	Bool getS8ImagesSupported() const
-	{
-		return m_s8ImagesSupported;
-	}
-
-	Bool getD24S8ImagesSupported() const
-	{
-		return m_d24S8ImagesSupported;
-	}
-
 	DescriptorSetFactory& getDescriptorSetFactory()
 	{
 		return m_descrFactory;
@@ -327,10 +312,6 @@ private:
 
 	PipelineCache m_pplineCache;
 
-	Bool m_r8g8b8ImagesSupported = false;
-	Bool m_s8ImagesSupported = false;
-	Bool m_d24S8ImagesSupported = false;
-
 	mutable HashMap<U64, StringAuto> m_vkHandleToName;
 	mutable SpinLock m_vkHandleToNameLock;
 

+ 5 - 43
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -248,52 +248,14 @@ Bool TextureImpl::imageSupported(const TextureInitInfo& init)
 	}
 }
 
-Error TextureImpl::initImage(const TextureInitInfo& init_)
+Error TextureImpl::initImage(const TextureInitInfo& init)
 {
-	TextureInitInfo init = init_;
-
 	// Check if format is supported
-	Bool supported;
-	while(!(supported = imageSupported(init)))
-	{
-		// Try to find a fallback
-		if(init.m_format >= Format::R8G8B8_UNORM && init.m_format <= Format::R8G8B8_SRGB)
-		{
-			ANKI_ASSERT(!(init.m_usage & TextureUsageBit::ALL_IMAGE) && "Can't do that ATM");
-			const U idx = U(init.m_format) - U(Format::R8G8B8_UNORM);
-			init.m_format = Format(U(Format::R8G8B8A8_UNORM) + idx);
-			ANKI_ASSERT(init.m_format >= Format::R8G8B8A8_UNORM && init.m_format <= Format::R8G8B8A8_SRGB);
-			m_format = init.m_format;
-			m_vkFormat = convertFormat(m_format);
-			m_workarounds = TextureImplWorkaround::R8G8B8_TO_R8G8B8A8;
-		}
-		else if(init.m_format == Format::S8_UINT)
-		{
-			ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
-						&& "Can't do that ATM");
-			init.m_format = Format::D24_UNORM_S8_UINT;
-			m_format = init.m_format;
-			m_vkFormat = convertFormat(m_format);
-			m_workarounds = TextureImplWorkaround::S8_TO_D24S8;
-		}
-		else if(init.m_format == Format::D24_UNORM_S8_UINT)
-		{
-			ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
-						&& "Can't do that ATM");
-			init.m_format = Format::D32_SFLOAT_S8_UINT;
-			m_format = init.m_format;
-			m_vkFormat = convertFormat(m_format);
-			m_workarounds = TextureImplWorkaround::D24S8_TO_D32S8;
-		}
-		else
-		{
-			break;
-		}
-	}
-
-	if(!supported)
+	if(!imageSupported(init))
 	{
-		ANKI_VK_LOGE("Unsupported texture format: %u", U32(init.m_format));
+		ANKI_VK_LOGE("TextureInitInfo contains a combination of parameters that it's not supported by the device. "
+					 "Texture format is %s",
+					 getFormatInfo(init.m_format).m_name);
 		return Error::FUNCTION_FAILED;
 	}
 

+ 0 - 11
AnKi/Gr/Vulkan/TextureImpl.h

@@ -20,15 +20,6 @@ class TextureUsageState;
 /// @addtogroup vulkan
 /// @{
 
-enum class TextureImplWorkaround : U8
-{
-	NONE,
-	R8G8B8_TO_R8G8B8A8 = 1 << 0,
-	S8_TO_D24S8 = 1 << 1,
-	D24S8_TO_D32S8 = 1 << 2,
-};
-ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureImplWorkaround)
-
 /// A Vulkan image view with some extra data.
 class MicroImageView
 {
@@ -102,8 +93,6 @@ public:
 
 	VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
 
-	TextureImplWorkaround m_workarounds = TextureImplWorkaround::NONE;
-
 	VkImageViewCreateInfo m_viewCreateInfoTemplate;
 	VkImageViewASTCDecodeModeEXT m_astcDecodeMode;
 

+ 12 - 1
AnKi/Importer/ImageImporter.cpp

@@ -451,7 +451,7 @@ static ANKI_USE_RESULT Error loadFirstMipmap(const ImageImporterConfig& config,
 
 		if(ctx.m_depth > 1)
 		{
-			memcpy(mip0.m_surfacesOrVolume.getBegin() + i * dataSize, data, dataSize);
+			memcpy(mip0.m_surfacesOrVolume[0].m_pixels.getBegin() + i * dataSize, data, dataSize);
 		}
 		else
 		{
@@ -864,8 +864,19 @@ static ANKI_USE_RESULT Error importImageInternal(const ImageImporterConfig& conf
 			ANKI_IMPORTER_LOGW("Input images have alpha but that can't be supported with BC6H");
 		}
 
+		if(!!(config.m_compressions & ImageBinaryDataCompression::RAW))
+		{
+			ANKI_IMPORTER_LOGE("Can't support both BC6H (which is 3 component) and RAW which requires 4 compoments");
+			return Error::USER_DATA;
+		}
+
 		desiredChannelCount = 3;
 	}
+	else if(!!(config.m_compressions & ImageBinaryDataCompression::RAW))
+	{
+		// Always ask for 4 components because desktop GPUs don't always like 3
+		desiredChannelCount = 4;
+	}
 	else if(config.m_noAlpha || channelCount == 1)
 	{
 		// no alpha or 1 component grey

+ 4 - 1
AnKi/Renderer/Scale.cpp

@@ -92,7 +92,10 @@ Error Scale::init()
 
 	// Descriptors
 	m_rtDesc = m_r->create2DRenderTargetDescription(
-		m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y(), Format::R8G8B8A8_UNORM, "Scaled");
+		m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y(),
+		(getGrManager().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::R8G8B8_UNORM
+																			  : Format::R8G8B8A8_UNORM,
+		"Scaled");
 	m_rtDesc.bake();
 
 	m_fbDescr.m_colorAttachmentCount = 1;

+ 5 - 3
AnKi/Renderer/TemporalAA.cpp

@@ -74,9 +74,11 @@ Error TemporalAA::initInternal()
 		m_rtTextures[i] = m_r->createAndClearRenderTarget(texinit);
 	}
 
-	m_tonemappedRtDescr =
-		m_r->create2DRenderTargetDescription(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
-											 Format::R8G8B8A8_UNORM, "TemporalAA Tonemapped");
+	m_tonemappedRtDescr = m_r->create2DRenderTargetDescription(
+		m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
+		(getGrManager().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::R8G8B8_UNORM
+																			  : Format::R8G8B8A8_UNORM,
+		"TemporalAA Tonemapped");
 	m_tonemappedRtDescr.bake();
 
 	m_fbDescr.m_colorAttachmentCount = 2;

BIN
EngineAssets/DefaultLut.ankitex


+ 3 - 0
ThirdParty/Stb/stb_image.h

@@ -5881,7 +5881,10 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req
 
    // convert to target component count
    if (req_comp && req_comp != tga_comp)
+   {
       tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height);
+      if (comp) *comp = req_comp;
+   }
 
    //   the things I do to get rid of an error message, and yet keep
    //   Microsoft's C compilers happy... [8^(