This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Galaxy S6 (SM-G920S)/Mali-T760 Vulkan 2D Array Layer Mipmap error

The mobile hardware spec :

Galaxy S6 (SM-G920s)

Android OS : 7.0 Nougat

GPU  : Mali-T760

GL_VERSION : OpenGL ES 3.2

Vulkan Version : 1.0.26

Hi I'm developing on my galaxy S6 and S8

But I think there is a problem on Mail-T760 Vulkan driver.

I made a feature that I can make a mipmap chain on texture cube.

I mean in the code 

VkImageCreateInfo imageInfo{ VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = TexCubeFormat;
imageInfo.mipLevels = calculatedMipLevels;
imageInfo.arrayLayers = 6; // because It's Texture Cube
...
// make VkImage


VkImageViewCreateInfo view{ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO };
view.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
view.format = TexCubeFormat;
view.components = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
view.subresourceRange.aspectMask = aspectMask;
view.subresourceRange.baseMipLevel = 0;
view.subresourceRange.levelCount = info.mipLevels;
view.subresourceRange.baseArrayLayer = 0;
view.subresourceRange.layerCount = 6; // because It's Texture Cube
view.image = image;
...
// make ImageView

// and then copy buffer to texture only in mipmip 0
std::vector<VkBufferImageCopy> bufferCopyRegions;
for (uint32_t face = 0; face < 6; face++)
{
	VkBufferImageCopy bufferCopyRegion = {};
	bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
	bufferCopyRegion.imageSubresource.mipLevel = 0;
	bufferCopyRegion.imageSubresource.baseArrayLayer = face;
	bufferCopyRegion.imageSubresource.layerCount = 1;
	bufferCopyRegion.imageExtent.width = info.extent.width;
	bufferCopyRegion.imageExtent.height = info.extent.height;
	bufferCopyRegion.imageExtent.depth = info.extent.depth;

	bufferCopyRegion.bufferOffset = offset;
	bufferCopyRegions.Add(bufferCopyRegion);

	// Increase offset into staging buffer for next face
	offset += OneTextureSize;
}

vkCmdCopyBufferToImage(
	copyCmd,
	stagingBuffer,
	image,
	VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
	static_cast<uint32_t>(bufferCopyRegions.Length()),
	bufferCopyRegions.data());
	
// and then build mipmap on each layer(+X, -X, +Y, -Y, +Z, -Z) of Texture Cube
VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.image = image;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.subresourceRange.aspectMask = subresourceRange.aspectMask;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 6;

VkImageBlit imageBlit{};
imageBlit.srcSubresource.aspectMask = subresourceRange.aspectMask;
imageBlit.srcSubresource.baseArrayLayer = 0;
imageBlit.srcSubresource.layerCount = 6; // because It's Texture Cube
imageBlit.srcOffsets[0] = { 0, 0, 0 };
imageBlit.srcOffsets[1].z = 1;
imageBlit.dstSubresource.aspectMask = subresourceRange.aspectMask;
imageBlit.dstSubresource.baseArrayLayer = 0;
imageBlit.dstSubresource.layerCount = 6; // because It's Texture Cube
imageBlit.dstOffsets[0] = { 0, 0, 0 }; 
imageBlit.dstOffsets[1].z = 1;

for (uint32 level = 1; level < info.mipLevels; ++level)
{
	barrier.subresourceRange.baseMipLevel = level - 1;
	barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
	barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
	barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
	barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;

	vkCmdPipelineBarrier(flyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
		0, 0, nullptr, 0, nullptr, 1, &barrier);

	// Source
	imageBlit.srcSubresource.mipLevel = level - 1;
	imageBlit.srcOffsets[1].x = MAX(int32_t(info.extent.width >> (level - 1)), 1);
	imageBlit.srcOffsets[1].y = MAX(int32_t(info.extent.height >> (level - 1)), 1);

	// Destination
	imageBlit.dstSubresource.mipLevel = level;
	imageBlit.dstOffsets[1].x = MAX(int32_t(info.extent.width >> level), 1);
	imageBlit.dstOffsets[1].y = MAX(int32_t(info.extent.height >> level), 1);

	// Blit from previous level
	vkCmdBlitImage(
		flyCmd,
		image,
		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
		image,
		VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
		1,
		&imageBlit,
		mipmapFilter
	);

	// convert the previous layout into the final layout
	barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
	barrier.newLayout = imageLayout;
	barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
	barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
	vkCmdPipelineBarrier(flyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
		0, nullptr,
		0, nullptr,
		1, &barrier);
}

// convert the layout into the finaly layout on the final mipmap chain
barrier.subresourceRange.baseMipLevel = info.mipLevels - 1;
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = imageLayout;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
vkCmdPipelineBarrier(flyCmd, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
	0, nullptr,
	0, nullptr,
	1, &barrier);

I made a mipmap for all array layers of texture2D. Because It's texture cube, I used the array layer count 6.

With this code, The code works with what I think on the Desktop, and other Galaxy S8 with Mali-G71.

But It does not work on Galaxy S6 with Mali-T760.

I checked it with RenderDoc. It shows that There are only black pixels from second mipmaps to last mipmaps on every mipmap chain except for the X+ layer.

X+ layer has all perfect mipmap pixels. But others have definitely mipmap chains, but only have black colors.

So the result is..

and the renderdoc result is