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

Parents
  • Hi, 

    I've moved this to the Graphics and Gaming forum, so more of the graphics team see this.

    The Galaxy S6 shipped with very early Vulkan drivers, so in all honesty it wouldn't surprise me if you hit driver bugs. It was a useful platform for early experimentation as it was the only phone with Vulkan at the time, but for production use of Vulkan we're really recommend targeting the Galaxy S8 or later, falling back to OpenGL ES on earlier models.

    HTH, 
    Pete

Reply
  • Hi, 

    I've moved this to the Graphics and Gaming forum, so more of the graphics team see this.

    The Galaxy S6 shipped with very early Vulkan drivers, so in all honesty it wouldn't surprise me if you hit driver bugs. It was a useful platform for early experimentation as it was the only phone with Vulkan at the time, but for production use of Vulkan we're really recommend targeting the Galaxy S8 or later, falling back to OpenGL ES on earlier models.

    HTH, 
    Pete

Children