Пример #1
0
vk::wsi::Display* VulkanPlatform::createWsiDisplay (vk::wsi::Type wsiType) const
{
	if (wsiType != vk::wsi::TYPE_MACOS)
		TCU_THROW(NotSupportedError, "WSI type not supported");

	return new VulkanDisplay();
}
Пример #2
0
vk::wsi::Display* VulkanPlatform::createWsiDisplay (vk::wsi::Type wsiType) const
{
	switch(wsiType)
	{
#if defined (DEQP_SUPPORT_X11)
	case vk::wsi::TYPE_XLIB:
		return new VulkanDisplayXlib(MovePtr<x11::DisplayBase>(new x11::XlibDisplay(m_eventState,"")));
		break;
#endif // DEQP_SUPPORT_X11
#if defined (DEQP_SUPPORT_XCB)
	case vk::wsi::TYPE_XCB:
		return new VulkanDisplayXcb(MovePtr<x11::DisplayBase>(new x11::XcbDisplay(m_eventState,"")));
		break;
#endif // DEQP_SUPPORT_XCB
#if defined (DEQP_SUPPORT_WAYLAND)
	case vk::wsi::TYPE_WAYLAND:
		return new VulkanDisplayWayland(MovePtr<wayland::Display>(new wayland::Display(m_eventState, DE_NULL)));
		break;
#endif // DEQP_SUPPORT_WAYLAND

	default:
		TCU_THROW(NotSupportedError, "WSI type not supported");

	};
}
/** Stub init method */
void TextureFilterAnisotropicQueriesTestCase::init()
{
	glu::ContextType contextType = m_context.getRenderContext().getType();
	if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
		!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") &&
		!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic"))
	{
		TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported");
	}
}
Пример #4
0
void ReadPixelsTest::getFormatInfo (tcu::TextureFormat& format, GLint& glFormat, GLint& glType, int& pixelSize)
{
	if (m_chooseFormat)
	{
		GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glFormat));
		GLU_CHECK_CALL(glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glType));

		if (glFormat != GL_RGBA && glFormat != GL_BGRA && glFormat != GL_RGB)
			TCU_THROW(NotSupportedError, ("Unsupported IMPLEMENTATION_COLOR_READ_FORMAT: " + de::toString(glu::getPixelFormatStr(glFormat))).c_str());
		if (glu::getTypeName(glType) == DE_NULL)
			TCU_THROW(NotSupportedError, ("Unsupported GL_IMPLEMENTATION_COLOR_READ_TYPE: " + de::toString(tcu::Format::Hex<4>(glType))).c_str());

		format = glu::mapGLTransferFormat(glFormat, glType);
		pixelSize = format.getPixelSize();
	}
	else
	{
		format		= tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
		pixelSize	= 1 * 4;
		glFormat	= GL_RGBA;
		glType		= GL_UNSIGNED_BYTE;
	}
}
void ShaderMultiDrawArraysIndirectCountParametersTestCase::initChild()
{
	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_indirect_parameters"))
		TCU_THROW(NotSupportedError, "Extension GL_ARB_indirect_parameters not supported");

	const Functions& gl = m_context.getRenderContext().getFunctions();

	// Set expected result vector [x, y, red, green, blue]
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -1.0f + 0.05f, 0.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -1.0f + 0.15f, 1.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -1.0f + 0.05f, 1.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -1.0f + 0.15f, 1.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -0.8f + 0.05f, 0.0f, 1.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -0.8f + 0.15f, 0.0f, 1.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -0.8f + 0.05f, 0.0f, 1.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -0.8f + 0.15f, 0.0f, 1.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -0.6f + 0.05f, 0.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.05f, -0.6f + 0.15f, 0.0f, 0.0f, 0.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -0.6f + 0.05f, 0.0f, 0.0f, 1.0f));
	m_resultPoints.push_back(ResultPoint(-1.0f + 0.15f, -0.6f + 0.15f, 0.0f, 0.0f, 1.0f));

	const SDPDrawArraysIndirectCommand indirect[] = {
		{ 5, 1, 1, 0 }, { 6, 1, 0, 1 }, { 4, 1, 2, 2 },
	};

	const GLushort parameters[] = { 1, 1, 1 };

	// Setup indirect command buffer
	gl.genBuffers(1, &m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_drawIndirectBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_DRAW_INDIRECT_BUFFER, 4 * sizeof(SDPDrawArraysIndirectCommand), indirect, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup indirect command buffer
	gl.genBuffers(1, &m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_PARAMETER_BUFFER_ARB, m_parameterBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_PARAMETER_BUFFER_ARB, 3 * sizeof(GLushort), parameters, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
}
/** Stub init method */
void ShaderDrawParametersTestBase::init()
{
	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_draw_parameters"))
		TCU_THROW(NotSupportedError, "Extension GL_ARB_shader_draw_parameters not supported");

	initChild();

	const Functions& gl = m_context.getRenderContext().getFunctions();

	const GLfloat vertices[] = {
		-1.0f, -1.0f, 0.0f, -1.0f, -0.8f, 0.0f, -0.9f, -1.0f, 0.0f,
		-0.9f, -0.8f, 0.0f, -0.8f, -1.0f, 0.0f, -0.8f, -0.8f, 0.0f,
	};

	const GLushort elements[] = { 0, 1, 2, 3, 4, 5 };

	// Generate vertex array object
	gl.genVertexArrays(1, &m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");

	gl.bindVertexArray(m_vao);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");

	// Setup vertex array buffer
	gl.genBuffers(1, &m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_ARRAY_BUFFER, m_arrayBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");

	// Setup element array buffer
	gl.genBuffers(1, &m_elementBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");

	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");

	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLushort), elements, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
}
vk::Move<vk::VkDeviceMemory> allocateExportableMemory (const vk::InstanceInterface&					vki,
													   vk::VkPhysicalDevice							physicalDevice,
													   const vk::DeviceInterface&					vkd,
													   vk::VkDevice									device,
													   const vk::VkMemoryRequirements&				requirements,
													   vk::VkExternalMemoryHandleTypeFlagBitsKHR	externalType,
													   bool											hostVisible,
													   vk::VkBuffer									buffer)
{
	const vk::VkPhysicalDeviceMemoryProperties properties = vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice);

	for (deUint32 memoryTypeIndex = 0; (1u << memoryTypeIndex) <= requirements.memoryTypeBits; memoryTypeIndex++)
	{
		if (((requirements.memoryTypeBits & (1u << memoryTypeIndex)) != 0)
			&& (((properties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) == hostVisible))
		{
			const vk::VkMemoryDedicatedAllocateInfoKHR	dedicatedInfo	=
			{
				vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
				DE_NULL,

				(vk::VkImage)0,
				buffer
			};
			const vk::VkExportMemoryAllocateInfoKHR	exportInfo	=
			{
				vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
				!!buffer ? &dedicatedInfo : DE_NULL,
				(vk::VkExternalMemoryHandleTypeFlagsKHR)externalType
			};
			const vk::VkMemoryAllocateInfo			info		=
			{
				vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
				&exportInfo,
				requirements.size,
				memoryTypeIndex
			};
			return vk::allocateMemory(vkd, device, &info);
		}
	}

	TCU_THROW(NotSupportedError, "No supported memory type found");
}
/** Stub init method */
void TextureFilterAnisotropicDrawingTestCase::init()
{
	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic"))
		TCU_THROW(NotSupportedError, "GL_EXT_texture_filter_anisotropic not supported");

	const tcu::RenderTarget& rt = m_context.getRenderTarget();

	GLint width  = rt.getWidth();
	GLint height = rt.getHeight();

	if (width < 32 || height < 32)
		TCU_THROW(NotSupportedError, "Config not supported - render buffer size should be at least 32x32");

	m_vertex = "#version <VERSION>\n"
			   "\n"
			   "in highp vec3 vertex;\n"
			   "in highp <TEXCOORD_TYPE> inTexCoord;\n"
			   "out highp <TEXCOORD_TYPE> commonTexCoord;\n"
			   "\n"
			   "uniform highp mat4 projectionMatrix;\n"
			   "\n"
			   "void main()\n"
			   "{\n"
			   "    commonTexCoord = inTexCoord;\n"
			   "    gl_Position = vec4(vertex, 1.0) * projectionMatrix;\n"
			   "}\n";

	m_fragment = "#version <VERSION>\n"
				 "\n"
				 "in highp <TEXCOORD_TYPE> commonTexCoord;\n"
				 "out highp vec4 fragColor;\n"
				 "\n"
				 "uniform highp <SAMPLER_TYPE> tex;\n"
				 "\n"
				 "void main()\n"
				 "{\n"
				 "    fragColor = texture(tex, commonTexCoord);\n"
				 "}\n"
				 "\n";

	m_supportedTargets.clear();
	m_supportedTargets.push_back(GL_TEXTURE_2D);
	m_supportedTargets.push_back(GL_TEXTURE_2D_ARRAY);

	m_supportedInternalFormats.clear();
	m_supportedInternalFormats.push_back(GL_R8);
	m_supportedInternalFormats.push_back(GL_R8_SNORM);
	m_supportedInternalFormats.push_back(GL_RG8);
	m_supportedInternalFormats.push_back(GL_RG8_SNORM);
	m_supportedInternalFormats.push_back(GL_RGB8);
	m_supportedInternalFormats.push_back(GL_RGB8_SNORM);
	m_supportedInternalFormats.push_back(GL_RGB565);
	m_supportedInternalFormats.push_back(GL_RGBA4);
	m_supportedInternalFormats.push_back(GL_RGB5_A1);
	m_supportedInternalFormats.push_back(GL_RGBA8);
	m_supportedInternalFormats.push_back(GL_RGBA8_SNORM);
	m_supportedInternalFormats.push_back(GL_RGB10_A2);
	m_supportedInternalFormats.push_back(GL_SRGB8);
	m_supportedInternalFormats.push_back(GL_SRGB8_ALPHA8);
	m_supportedInternalFormats.push_back(GL_R16F);
	m_supportedInternalFormats.push_back(GL_RG16F);
	m_supportedInternalFormats.push_back(GL_RGB16F);
	m_supportedInternalFormats.push_back(GL_RGBA16F);
	m_supportedInternalFormats.push_back(GL_R11F_G11F_B10F);
	m_supportedInternalFormats.push_back(GL_RGB9_E5);
}
/** Stub init method */
void TextureFilterAnisotropicQueriesTestCase::init()
{
	if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic"))
		TCU_THROW(NotSupportedError, "GL_EXT_texture_filter_anisotropic not supported");
}
void SparseShaderIntrinsicsInstanceSampledBase::recordCommands (const VkCommandBuffer		commandBuffer,
																const VkImageCreateInfo&	imageSparseInfo,
																const VkImage				imageSparse,
																const VkImage				imageTexels,
																const VkImage				imageResidency)
{
	const InstanceInterface&		 instance			= m_context.getInstanceInterface();
	const DeviceInterface&			 deviceInterface	= getDeviceInterface();
	const VkPhysicalDevice			 physicalDevice		= m_context.getPhysicalDevice();
	const VkPhysicalDeviceProperties deviceProperties	= getPhysicalDeviceProperties(instance, physicalDevice);

	if (imageSparseInfo.extent.width  > deviceProperties.limits.maxFramebufferWidth  ||
		imageSparseInfo.extent.height > deviceProperties.limits.maxFramebufferHeight ||
		imageSparseInfo.arrayLayers   > deviceProperties.limits.maxFramebufferLayers)
	{
		TCU_THROW(NotSupportedError, "Image size exceeds allowed framebuffer dimensions");
	}

	// Check if device supports image format for sampled images
	if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
		TCU_THROW(NotSupportedError, "Device does not support image format for sampled images");

	// Check if device supports image format for color attachment
	if (!checkImageFormatFeatureSupport(instance, physicalDevice, imageSparseInfo.format, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
		TCU_THROW(NotSupportedError, "Device does not support image format for color attachment");

	// Make sure device supports VK_FORMAT_R32_UINT format for color attachment
	if (!checkImageFormatFeatureSupport(instance, physicalDevice, mapTextureFormat(m_residencyFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
		TCU_THROW(TestError, "Device does not support VK_FORMAT_R32_UINT format for color attachment");

	// Create buffer storing vertex data
	std::vector<tcu::Vec2> vertexData;

	vertexData.push_back(tcu::Vec2(-1.0f,-1.0f));
	vertexData.push_back(tcu::Vec2( 0.0f, 0.0f));

	vertexData.push_back(tcu::Vec2(-1.0f, 1.0f));
	vertexData.push_back(tcu::Vec2( 0.0f, 1.0f));

	vertexData.push_back(tcu::Vec2( 1.0f,-1.0f));
	vertexData.push_back(tcu::Vec2( 1.0f, 0.0f));

	vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));
	vertexData.push_back(tcu::Vec2( 1.0f, 1.0f));

	const VkDeviceSize			vertexDataSizeInBytes	= sizeInBytes(vertexData);
	const VkBufferCreateInfo	vertexBufferCreateInfo	= makeBufferCreateInfo(vertexDataSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

	m_vertexBuffer		= createBuffer(deviceInterface, getDevice(), &vertexBufferCreateInfo);
	m_vertexBufferAlloc	= bindBuffer(deviceInterface, getDevice(), getAllocator(), *m_vertexBuffer, MemoryRequirement::HostVisible);

	deMemcpy(m_vertexBufferAlloc->getHostPtr(), &vertexData[0], static_cast<std::size_t>(vertexDataSizeInBytes));
	flushMappedMemoryRange(deviceInterface, getDevice(), m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexDataSizeInBytes);

	// Create render pass
	const VkAttachmentDescription texelsAttachmentDescription =
	{
		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
		imageSparseInfo.format,								// VkFormat							format;
		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
	};

	const VkAttachmentDescription residencyAttachmentDescription =
	{
		(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags;
		mapTextureFormat(m_residencyFormat),				// VkFormat							format;
		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples;
		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp				loadOp;
		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp				storeOp;
		VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp				stencilLoadOp;
		VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp				stencilStoreOp;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout					initialLayout;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout					finalLayout;
	};

	const VkAttachmentDescription colorAttachmentsDescription[] = { texelsAttachmentDescription, residencyAttachmentDescription };

	const VkAttachmentReference texelsAttachmentReference =
	{
		0u,													// deUint32			attachment;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
	};

	const VkAttachmentReference residencyAttachmentReference =
	{
		1u,													// deUint32			attachment;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
	};

	const VkAttachmentReference colorAttachmentsReference[] = { texelsAttachmentReference, residencyAttachmentReference };

	const VkAttachmentReference depthAttachmentReference =
	{
		VK_ATTACHMENT_UNUSED,								// deUint32			attachment;
		VK_IMAGE_LAYOUT_UNDEFINED							// VkImageLayout	layout;
	};

	const VkSubpassDescription subpassDescription =
	{
		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
		0u,													// deUint32							inputAttachmentCount;
		DE_NULL,											// const VkAttachmentReference*		pInputAttachments;
		2u,													// deUint32							colorAttachmentCount;
		colorAttachmentsReference,							// const VkAttachmentReference*		pColorAttachments;
		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
		&depthAttachmentReference,							// const VkAttachmentReference*		pDepthStencilAttachment;
		0u,													// deUint32							preserveAttachmentCount;
		DE_NULL												// const deUint32*					pPreserveAttachments;
	};

	const VkRenderPassCreateInfo renderPassInfo =
	{
		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
		DE_NULL,											// const void*						pNext;
		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
		2u,													// deUint32							attachmentCount;
		colorAttachmentsDescription,						// const VkAttachmentDescription*	pAttachments;
		1u,													// deUint32							subpassCount;
		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
		0u,													// deUint32							dependencyCount;
		DE_NULL												// const VkSubpassDependency*		pDependencies;
	};

	m_renderPass = createRenderPass(deviceInterface, getDevice(), &renderPassInfo);

	// Create descriptor set layout
	DescriptorSetLayoutBuilder descriptorLayerBuilder;

	descriptorLayerBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);

	const Unique<VkDescriptorSetLayout> descriptorSetLayout(descriptorLayerBuilder.build(deviceInterface, getDevice()));

	// Create descriptor pool
	DescriptorPoolBuilder descriptorPoolBuilder;

	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, imageSparseInfo.mipLevels);

	descriptorPool = descriptorPoolBuilder.build(deviceInterface, getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageSparseInfo.mipLevels);

	// Create sampler object
	const tcu::Sampler			samplerObject(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::NEAREST_MIPMAP_NEAREST, tcu::Sampler::NEAREST);
	const VkSamplerCreateInfo	samplerCreateInfo = mapSampler(samplerObject, m_format);
	m_sampler = createSampler(deviceInterface, getDevice(), &samplerCreateInfo);

	struct PushConstants
	{
		deUint32	lod;
		deUint32	padding;			// padding needed to satisfy std430 rules
		float		lodWidth;
		float		lodHeight;
	};

	// Create pipeline layout
	const VkPushConstantRange lodConstantRange =
	{
		VK_SHADER_STAGE_FRAGMENT_BIT,	// VkShaderStageFlags	stageFlags;
		0u,								// deUint32			offset;
		sizeof(PushConstants),			// deUint32			size;
	};

	const VkPipelineLayoutCreateInfo pipelineLayoutParams =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
		DE_NULL,											// const void*						pNext;
		0u,													// VkPipelineLayoutCreateFlags		flags;
		1u,													// deUint32							setLayoutCount;
		&descriptorSetLayout.get(),							// const VkDescriptorSetLayout*		pSetLayouts;
		1u,													// deUint32							pushConstantRangeCount;
		&lodConstantRange,									// const VkPushConstantRange*		pPushConstantRanges;
	};

	const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, getDevice(), &pipelineLayoutParams));

	// Create graphics pipeline
	{
		Move<VkShaderModule> vertexModule	= createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0);
		Move<VkShaderModule> fragmentModule	= createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0);
		Move<VkShaderModule> geometryModule;

		if (imageSparseInfo.arrayLayers > 1u)
		{
			requireFeatures(instance, physicalDevice, FEATURE_GEOMETRY_SHADER);
			geometryModule = createShaderModule(deviceInterface, getDevice(), m_context.getBinaryCollection().get("geometry_shader"), (VkShaderModuleCreateFlags)0);
		}

		pipelines.push_back(makeVkSharedPtr(makeGraphicsPipeline(
			deviceInterface, getDevice(), *pipelineLayout, *m_renderPass, *vertexModule, *fragmentModule, *geometryModule)));
	}

	const VkPipeline graphicsPipeline = **pipelines[0];

	{
		const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);

		VkImageMemoryBarrier imageShaderAccessBarriers[3];

		imageShaderAccessBarriers[0] = makeImageMemoryBarrier
		(
			VK_ACCESS_TRANSFER_WRITE_BIT,
			VK_ACCESS_SHADER_READ_BIT,
			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
			imageSparse,
			fullImageSubresourceRange
		);

		imageShaderAccessBarriers[1] = makeImageMemoryBarrier
		(
			0u,
			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
			VK_IMAGE_LAYOUT_UNDEFINED,
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
			imageTexels,
			fullImageSubresourceRange
		);

		imageShaderAccessBarriers[2] = makeImageMemoryBarrier
		(
			0u,
			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
			VK_IMAGE_LAYOUT_UNDEFINED,
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
			imageResidency,
			fullImageSubresourceRange
		);

		deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 3u, imageShaderAccessBarriers);
	}

	imageSparseViews.resize(imageSparseInfo.mipLevels);
	imageTexelsViews.resize(imageSparseInfo.mipLevels);
	imageResidencyViews.resize(imageSparseInfo.mipLevels);
	m_framebuffers.resize(imageSparseInfo.mipLevels);
	descriptorSets.resize(imageSparseInfo.mipLevels);

	std::vector<VkClearValue> clearValues;
	clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
	clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));

	for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx)
	{
		const vk::VkExtent3D			mipLevelSize	= mipLevelExtents(imageSparseInfo.extent, mipLevelNdx);
		const vk::VkRect2D				renderArea		= makeRect2D(mipLevelSize);
		const VkViewport				viewport		= makeViewport(mipLevelSize);
		const VkImageSubresourceRange	mipLevelRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevelNdx, 1u, 0u, imageSparseInfo.arrayLayers);

		// Create color attachments image views
		imageTexelsViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageTexels, mapImageViewType(m_imageType), imageSparseInfo.format, mipLevelRange));
		imageResidencyViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageResidency, mapImageViewType(m_imageType), mapTextureFormat(m_residencyFormat), mipLevelRange));

		const VkImageView attachmentsViews[] = { **imageTexelsViews[mipLevelNdx], **imageResidencyViews[mipLevelNdx] };

		// Create framebuffer
		const VkFramebufferCreateInfo framebufferInfo =
		{
			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType                             sType;
			DE_NULL,									// const void*                                 pNext;
			(VkFramebufferCreateFlags)0,				// VkFramebufferCreateFlags                    flags;
			*m_renderPass,								// VkRenderPass                                renderPass;
			2u,											// uint32_t                                    attachmentCount;
			attachmentsViews,							// const VkImageView*                          pAttachments;
			mipLevelSize.width,							// uint32_t                                    width;
			mipLevelSize.height,						// uint32_t                                    height;
			imageSparseInfo.arrayLayers,				// uint32_t                                    layers;
		};

		m_framebuffers[mipLevelNdx] = makeVkSharedPtr(createFramebuffer(deviceInterface, getDevice(), &framebufferInfo));

		// Create descriptor set
		descriptorSets[mipLevelNdx] = makeVkSharedPtr(makeDescriptorSet(deviceInterface, getDevice(), *descriptorPool, *descriptorSetLayout));
		const VkDescriptorSet descriptorSet = **descriptorSets[mipLevelNdx];

		// Update descriptor set
		const VkImageSubresourceRange sparseImageSubresourceRange = sampledImageRangeToBind(imageSparseInfo, mipLevelNdx);

		imageSparseViews[mipLevelNdx] = makeVkSharedPtr(makeImageView(deviceInterface, getDevice(), imageSparse, mapImageViewType(m_imageType), imageSparseInfo.format, sparseImageSubresourceRange));

		const VkDescriptorImageInfo imageSparseDescInfo = makeDescriptorImageInfo(*m_sampler, **imageSparseViews[mipLevelNdx], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

		DescriptorSetUpdateBuilder descriptorUpdateBuilder;

		descriptorUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(BINDING_IMAGE_SPARSE), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSparseDescInfo);
		descriptorUpdateBuilder.update(deviceInterface, getDevice());

		// Begin render pass
		beginRenderPass(deviceInterface, commandBuffer, *m_renderPass, **m_framebuffers[mipLevelNdx], renderArea, (deUint32)clearValues.size(), &clearValues[0]);

		// Bind graphics pipeline
		deviceInterface.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);

		// Bind descriptor set
		deviceInterface.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);

		// Bind vertex buffer
		{
			const VkDeviceSize offset = 0ull;
			deviceInterface.cmdBindVertexBuffers(commandBuffer, 0u, 1u, &m_vertexBuffer.get(), &offset);
		}

		// Bind Viewport
		deviceInterface.cmdSetViewport(commandBuffer, 0u, 1u, &viewport);

		// Bind Scissor Rectangle
		deviceInterface.cmdSetScissor(commandBuffer, 0u, 1u, &renderArea);

		const PushConstants pushConstants =
		{
			mipLevelNdx,
			0u,											// padding
			static_cast<float>(mipLevelSize.width),
			static_cast<float>(mipLevelSize.height)
		};

		// Update push constants
		deviceInterface.cmdPushConstants(commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(PushConstants), &pushConstants);

		// Draw full screen quad
		deviceInterface.cmdDraw(commandBuffer, 4u, 1u, 0u, 0u);

		// End render pass
		endRenderPass(deviceInterface, commandBuffer);
	}

	{
		const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers);

		VkImageMemoryBarrier imageOutputTransferSrcBarriers[2];

		imageOutputTransferSrcBarriers[0] = makeImageMemoryBarrier
		(
			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
			VK_ACCESS_TRANSFER_READ_BIT,
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
			imageTexels,
			fullImageSubresourceRange
		);

		imageOutputTransferSrcBarriers[1] = makeImageMemoryBarrier
		(
			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
			VK_ACCESS_TRANSFER_READ_BIT,
			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
			imageResidency,
			fullImageSubresourceRange
		);

		deviceInterface.cmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputTransferSrcBarriers);
	}
}