text: /*------------------------------------------------------------------------
  * Vulkan Conformance Tests
  * ------------------------
  *
  * Copyright (c) 2018 The Khronos Group Inc.
  * Copyright (c) 2018 Intel Corporation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  *//*!
  * \file
  * \brief VK_EXT_conditional_rendering extension tests.
  *//*--------------------------------------------------------------------*/
  
  #include "vktConditionalDrawAndClearTests.hpp"
  
  #include "vktTestCaseUtil.hpp"
  #include "vktDrawBaseClass.hpp"
  #include "vktDrawTestCaseUtil.hpp"
  #include "vkBuilderUtil.hpp"
  #include "vkObjUtil.hpp"
  #include "vkCmdUtil.hpp"
  #include "vkQueryUtil.hpp"
  #include "vkTypeUtil.hpp"
  
  #include <bitset>
  
  namespace vkt
  {
  namespace conditional
  {
  namespace
  {
  
  using namespace vk;
  using namespace Draw;
  
  struct ClearTestParams
  {
  	bool	m_discard;
  	bool	m_invert;
  	bool	m_testDepth;
  	bool	m_partialClear;
  	bool	m_useOffset;
  	bool	m_clearAttachmentTwice;
  };
  
  const ClearTestParams clearColorTestGrid[] =
  {
  	{ false,	false,		false,		false,		false,		false },
  	{ true,		false,		false,		false,		false,		false },
  	{ false,	true,		false,		false,		false,		false },
  	{ true,		true,		false,		false,		false,		false },
  	{ false,	false,		false,		true,		false,		false },
  	{ true,		false,		false,		true,		false,		false },
  	{ false,	true,		false,		true,		false,		false },
  	{ true,		true,		false,		true,		false,		false },
  	{ false,	false,		false,		true,		true,		false },
  	{ true,		false,		false,		true,		true,		false },
  	{ false,	true,		false,		true,		true,		false },
  	{ true,		true,		false,		true,		true,		false },
  	{ true,		true,		false,		false,		true,		false },
  };
  
  const ClearTestParams clearDepthTestGrid[] =
  {
  	{ false,	false,		true,		false,		false,		false },
  	{ true,		false,		true,		false,		false,		false },
  	{ false,	 true,		true,		false,		false,		false },
  	{ true,		true,		true,		false,		false,		false },
  	{ false,	false,		true,		true,		false,		false },
  	{ true,		false,		true,		true,		false,		false },
  	{ false,	true,		true,		true,		false,		false },
  	{ true,		true,		true,		true,		false,		false },
  	{ false,	false,		true,		true,		true,		false },
  	{ true,		false,		true,		true,		true,		false },
  	{ false,	true,		true,		true,		true,		false },
  	{ true,		true,		true,		true,		true,		false },
  };
  
  const ClearTestParams clearColorTwiceGrid[] =
  {
  	{ false,	false,		false,		false,		false,		true },
  	{ true,		false,		false,		false,		false,		true },
  	{ false,	true,		false,		false,		false,		true },
  	{ true,		true,		false,		false,		false,		true },
  	{ false,	true,		false,		true,		true,		true },
  	{ true,		true,		false,		true,		true,		true }
  };
  
  const ClearTestParams clearDepthTwiceGrid[] =
  {
  	{ false,	false,		true,		false,		false,		true },
  	{ true,		false,		true,		false,		false,		true },
  	{ false,	true,		true,		false,		false,		true },
  	{ true,		true,		true,		false,		false,		true },
  	{ false,	true,		true,		true,		true,		true },
  	{ true,		true,		true,		true,		true,		true }
  };
  
  enum TogglePredicateMode { FILL, COPY, NONE };
  
  struct DrawTestParams
  {
  	bool						m_discard; //controls the setting of the predicate for conditional rendering.Initial state, may be toggled later depending on the m_togglePredicate setting.
  	bool						m_invert;
  	bool						m_useOffset;
  	deUint32					m_beginSequenceBits; //bits 0..3 control BEFORE which of the 4 draw calls the vkCmdBeginConditionalRenderingEXT call is executed. Least significant bit corresponds to the first draw call.
  	deUint32					m_endSequenceBits; //bits 0..3 control AFTER which of the 4 draw calls the vkCmdEndConditionalRenderingEXT call is executed. Least significant bit corresponds to the first draw call.
  	deUint32					m_resultBits; //used for reference image preparation.
  	bool						m_togglePredicate; //if true, toggle the predicate setting before rendering.
  	TogglePredicateMode			m_toggleMode; //method of the predicate toggling
  };
  
  enum
  {
  	b0000 = 0x0,
  	b0001 = 0x1,
  	b0010 = 0x2,
  	b0011 = 0x3,
  	b0100 = 0x4,
  	b0101 = 0x5,
  	b0110 = 0x6,
  	b0111 = 0x7,
  	b1000 = 0x8,
  	b1001 = 0x9,
  	b1010 = 0xA,
  	b1011 = 0xB,
  	b1100 = 0xC,
  	b1101 = 0xD,
  	b1110 = 0xE,
  	b1111 = 0xF,
  };
  
  const DrawTestParams drawTestGrid[] =
  {
  	{ false,	false,	false,	b0001, b1000, b1111, false,	NONE },
  	{ true,		false,	false,	b0001, b1000, b0000, false,	NONE },
  	{ true,		false,	false,	b0001, b0001, b1110, false,	NONE },
  	{ true,		false,	false,	b1111, b1111, b0000, false,	NONE },
  	{ true,		false,	false,	b0010, b0010, b1101, false,	NONE },
  	{ true,		true,	false,	b1010, b1010, b0101, false,	NONE },
  	{ false,	true,	true,	b1010, b1010, b1111, false,	NONE },
  	{ true,		true,	true,	b0010, b1000, b0001, false,	NONE },
  	{ true,		true,	true,	b1001, b1001, b0110, false,	NONE },
  	{ true,		true,	true,	b0010, b1000, b1111, true,	FILL },
  	{ true,		true,	true,	b1001, b1001, b1111, true,	FILL },
  	{ false,	true,	true,	b1001, b1001, b0110, true,	FILL },
  	{ true,		true,	true,	b0010, b1000, b1111, true,	COPY },
  	{ true,		true,	true,	b1001, b1001, b1111, true,	COPY },
  	{ false,	true,	true,	b1001, b1001, b0110, true,	COPY },
  };
  
  std::string generateClearTestName(const ClearTestParams& clearTestParams)
  {
  	std::string		name			=	(clearTestParams.m_discard		? "discard_"	:	"no_discard_");
  	name			+=	(clearTestParams.m_invert		? "invert_"		:	"no_invert_");
  	name			+=	(clearTestParams.m_partialClear	? "partial_"	:	"full_");
  	name			+=	(clearTestParams.m_useOffset	? "offset"		:	"no_offset");
  	return name;
  }
  
  inline deUint32 getBit(deUint32 src, int ndx)
  {
  	return (src >> ndx) & 1;
  }
  
  inline bool isBitSet(deUint32 src, int ndx)
  {
  	return getBit(src, ndx) != 0;
  }
  
  class ConditionalRenderingBaseTestInstance : public TestInstance
  {
  public:
  									ConditionalRenderingBaseTestInstance					(Context& context);
  protected:
  	virtual tcu::TestStatus			iterate													(void) = 0;
  	void							createInitBufferWithPredicate							(bool discard, bool invert, deUint32 offsetMultiplier, VkBufferUsageFlagBits extraUsage);
  	void							createTargetColorImageAndImageView						(void);
  	void							createTargetDepthImageAndImageView						(void);
  	void							createRenderPass										(VkFormat format, VkImageLayout layout);
  	void							createFramebuffer										(VkImageView imageView);
  	void							clearWithClearColorImage								(const VkClearColorValue& color);
  	void							clearWithClearDepthStencilImage							(const VkClearDepthStencilValue& value);
  	void							clearColorWithClearAttachments							(const VkClearColorValue& color, bool partial);
  	void							clearDepthWithClearAttachments							(const VkClearDepthStencilValue& depthStencil, bool partial);
  	void							createResultBuffer										(VkFormat format);
  	void							createVertexBuffer										(void);
  	void							createPipelineLayout									(void);
  	void							createAndUpdateDescriptorSet							(void);
  	void							createPipeline											(void);
  	void							copyResultImageToBuffer									(VkImageAspectFlags imageAspectFlags, VkImage image);
  	void							draw													(void);
  	void							imageMemoryBarrier										(VkImage image, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout,
  																							VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageAspectFlags imageAspectFlags);
  	void							bufferMemoryBarrier										(VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
  																							VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask);
  	void							prepareReferenceImageOneColor							(tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColor);
  	void							prepareReferenceImageOneColor							(tcu::PixelBufferAccess& reference, const tcu::Vec4& color);
  	void							prepareReferenceImageOneDepth							(tcu::PixelBufferAccess& reference, const VkClearDepthStencilValue& clearValue);
  	void							prepareReferenceImageDepthClearPartial					(tcu::PixelBufferAccess& reference, const VkClearDepthStencilValue& clearValueInitial, const VkClearDepthStencilValue& clearValueFinal);
  	void							prepareReferenceImageColorClearPartial					(tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColorInitial, const VkClearColorValue& clearColorFinal);
  
  	const InstanceInterface&		m_vki;
  	const DeviceInterface&			m_vkd;
  	const VkDevice					m_device;
  	const VkPhysicalDevice			m_physicalDevice;
  	const VkQueue					m_queue;
  	de::SharedPtr<Buffer>			m_conditionalRenderingBuffer;
  	de::SharedPtr<Buffer>			m_resultBuffer;
  	de::SharedPtr<Buffer>			m_vertexBuffer;
  	de::SharedPtr<Image>			m_colorTargetImage;
  	de::SharedPtr<Image>			m_depthTargetImage;
  	Move<VkImageView>				m_colorTargetView;
  	Move<VkImageView>				m_depthTargetView;
  	Move<VkRenderPass>				m_renderPass;
  	Move<VkFramebuffer>				m_framebuffer;
  	Move<VkCommandPool>				m_cmdPool;
  	Move<VkCommandBuffer>			m_cmdBufferPrimary;
  	Move<VkDescriptorPool>			m_descriptorPool;
  	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
  	Move<VkDescriptorSet>			m_descriptorSet;
  	Move<VkPipelineLayout>			m_pipelineLayout;
  	Move<VkShaderModule>			m_vertexShaderModule;
  	Move<VkShaderModule>			m_fragmentShaderModule;
  	Move<VkPipeline>				m_pipeline;
  	VkDeviceSize					m_conditionalRenderingBufferOffset;
  
  	enum
  	{
  		WIDTH = 256,
  		HEIGHT = 256
  	};
  };
  
  class ConditionalRenderingClearAttachmentsTestInstance : public ConditionalRenderingBaseTestInstance
  {
  public:
  									ConditionalRenderingClearAttachmentsTestInstance		(Context& context, const ClearTestParams& testParams);
  protected:
  	virtual tcu::TestStatus			iterate													(void);
  	ClearTestParams					m_testParams;
  };
  
  class ConditionalRenderingDrawTestInstance : public ConditionalRenderingBaseTestInstance
  {
  public:
  									ConditionalRenderingDrawTestInstance					(Context& context, const DrawTestParams& testParams);
  protected:
  	//Execute 4 draw calls, each can be drawn with or without conditional rendering. Each draw call renders to the different part of an image - this is achieved by
  	//using push constant and 'discard' in the fragment shader. This way it is possible to tell which of the rendering command were discarded by the conditional rendering mechanism.
  	virtual tcu::TestStatus			iterate													(void);
  	void							createPipelineLayout									(void);
  	void							prepareReferenceImage									(tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColor, deUint32 resultBits);
  
  	DrawTestParams					m_testParams;
  	de::SharedPtr<Buffer>			m_conditionalRenderingBufferForCopy;
  };
  
  class ConditionalRenderingUpdateBufferWithDrawTestInstance : public ConditionalRenderingBaseTestInstance
  {
  public:
  									ConditionalRenderingUpdateBufferWithDrawTestInstance	(Context& context, bool testParams);
  protected:
  	virtual tcu::TestStatus			iterate													(void);
  	void							createAndUpdateDescriptorSets							(void);
  	void							createPipelines											(void);
  	void							createRenderPass										(VkFormat format, VkImageLayout layout);
  	Move<VkDescriptorSet>			m_descriptorSetUpdate;
  	Move<VkShaderModule>			m_vertexShaderModuleDraw;
  	Move<VkShaderModule>			m_fragmentShaderModuleDraw;
  	Move<VkShaderModule>			m_vertexShaderModuleUpdate;
  	Move<VkShaderModule>			m_fragmentShaderModuleDiscard;
  	Move<VkPipeline>				m_pipelineDraw;
  	Move<VkPipeline>				m_pipelineUpdate;
  	bool							m_testParams;
  };
  
  ConditionalRenderingBaseTestInstance::ConditionalRenderingBaseTestInstance (Context& context)
  	: TestInstance							(context)
  	, m_vki									(m_context.getInstanceInterface())
  	, m_vkd									(m_context.getDeviceInterface())
  	, m_device								(m_context.getDevice())
  	, m_physicalDevice						(m_context.getPhysicalDevice())
  	, m_queue								(m_context.getUniversalQueue())
  	, m_conditionalRenderingBufferOffset	(0)
  {
  }
  
  void ConditionalRenderingBaseTestInstance::createInitBufferWithPredicate (bool discard, bool invert, deUint32 offsetMultiplier = 0, VkBufferUsageFlagBits extraUsage = (VkBufferUsageFlagBits)0)
  {
  	m_conditionalRenderingBufferOffset		= sizeof(deUint32) * offsetMultiplier;
  
  	const VkDeviceSize						dataSize										= sizeof(deUint32) + m_conditionalRenderingBufferOffset;
  	deUint32								predicate										= discard ? invert : !invert;
  
  	m_conditionalRenderingBuffer			= Buffer::createAndAlloc(m_vkd, m_device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT | extraUsage), m_context.getDefaultAllocator(),
  																									   MemoryRequirement::HostVisible);
  
  	void *									conditionalRenderingBufferDataPointer			= static_cast<char*>(m_conditionalRenderingBuffer->getBoundMemory().getHostPtr()) + m_conditionalRenderingBufferOffset;
  
  	deMemcpy(conditionalRenderingBufferDataPointer, &predicate, static_cast<size_t>(sizeof(deUint32)));
  	flushMappedMemoryRange(m_vkd, m_device, m_conditionalRenderingBuffer->getBoundMemory().getMemory(), m_conditionalRenderingBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
  }
  
  void ConditionalRenderingBaseTestInstance::createTargetColorImageAndImageView (void)
  {
  	const VkExtent3D			targetImageExtent		= { WIDTH, HEIGHT, 1 };
  
  	const ImageCreateInfo		targetImageCreateInfo(	VK_IMAGE_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
  														VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
  
  	m_colorTargetImage			= Image::createAndAlloc(m_vkd, m_device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
  
  	const ImageViewCreateInfo	colorTargetViewInfo(m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_R8G8B8A8_UNORM);
  
  	m_colorTargetView			= createImageView(m_vkd, m_device, &colorTargetViewInfo);
  }
  
  void ConditionalRenderingBaseTestInstance::createTargetDepthImageAndImageView (void)
  {
  	const VkExtent3D			targetImageExtent		= { WIDTH, HEIGHT, 1 };
  
  	const ImageCreateInfo		targetImageCreateInfo(VK_IMAGE_TYPE_2D, VK_FORMAT_D32_SFLOAT, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
  													  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
  
  	m_depthTargetImage			= Image::createAndAlloc(m_vkd, m_device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
  
  	const ImageViewCreateInfo	depthTargetViewInfo(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D32_SFLOAT);
  
  	m_depthTargetView			= createImageView(m_vkd, m_device, &depthTargetViewInfo);
  }
  
  void ConditionalRenderingBaseTestInstance::createRenderPass (VkFormat format, VkImageLayout layout)
  {
  	RenderPassCreateInfo			renderPassCreateInfo;
  
  	renderPassCreateInfo.addAttachment(AttachmentDescription(format,
  															 VK_SAMPLE_COUNT_1_BIT,
  															 VK_ATTACHMENT_LOAD_OP_LOAD,
  															 VK_ATTACHMENT_STORE_OP_STORE,
  															 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  															 VK_ATTACHMENT_STORE_OP_STORE,
  															 isDepthStencilFormat(format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  															 isDepthStencilFormat(format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
  
  	const VkAttachmentReference		attachmentReference =
  	{
  		0u,														// deUint32				attachment
  		layout													// VkImageLayout		layout
  	};
  
  	renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
  													   0,
  													   0,
  													   DE_NULL,
  													   isDepthStencilFormat(format) ? 0 : 1,
  													   isDepthStencilFormat(format) ? DE_NULL : &attachmentReference,
  													   DE_NULL,
  													   isDepthStencilFormat(format) ? attachmentReference : AttachmentReference(),
  													   0,
  													   DE_NULL));
  
  	m_renderPass					= vk::createRenderPass(m_vkd, m_device, &renderPassCreateInfo);
  }
  
  void ConditionalRenderingBaseTestInstance::createFramebuffer (VkImageView imageView)
  {
  	const VkFramebufferCreateInfo	framebufferCreateInfo =
  	{
  		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType
  		DE_NULL,											// const void*					pNext
  		(VkFramebufferCreateFlags)0,						// VkFramebufferCreateFlags		flags;
  		*m_renderPass,										// VkRenderPass					renderPass
  		1,													// deUint32						attachmentCount
  		&imageView,											// const VkImageView*			pAttachments
  		WIDTH,												// deUint32						width
  		HEIGHT,												// deUint32						height
  		1													// deUint32						layers
  	};
  	m_framebuffer					= vk::createFramebuffer(m_vkd, m_device, &framebufferCreateInfo);
  }
  
  void ConditionalRenderingBaseTestInstance::imageMemoryBarrier (	VkImage image, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageLayout oldLayout, VkImageLayout newLayout,
  																VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageAspectFlags imageAspectFlags)
  {
  	const struct VkImageSubresourceRange	subRangeColor =
  	{
  		imageAspectFlags,								// VkImageAspectFlags		aspectMask
  		0u,												// deUint32					baseMipLevel
  		1u,												// deUint32					mipLevels
  		0u,												// deUint32					baseArrayLayer
  		1u,												// deUint32					arraySize
  	};
  	const VkImageMemoryBarrier				imageBarrier =
  	{
  		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType
  		DE_NULL,										// const void*				pNext
  		srcAccessMask,									// VkAccessFlags			srcAccessMask
  		dstAccessMask,									// VkAccessFlags			dstAccessMask
  		oldLayout,										// VkImageLayout			oldLayout
  		newLayout,										// VkImageLayout			newLayout
  		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex
  		VK_QUEUE_FAMILY_IGNORED,						// deUint32					dstQueueFamilyIndex
  		image,											// VkImage					image
  		subRangeColor									// VkImageSubresourceRange	subresourceRange
  	};
  
  	m_vkd.cmdPipelineBarrier(*m_cmdBufferPrimary, srcStageMask, dstStageMask, DE_FALSE, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
  }
  
  void ConditionalRenderingBaseTestInstance::bufferMemoryBarrier (VkBuffer buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
  																VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask)
  {
  	const VkBufferMemoryBarrier bufferBarrier =
  	{
  		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,		//VkStructureType			sType;
  		DE_NULL,										//const void*				pNext;
  		srcAccessMask,									//VkAccessFlags				srcAccessMask;
  		dstAccessMask,									//VkAccessFlags				dstAccessMask;
  		VK_QUEUE_FAMILY_IGNORED,						//uint32_t					srcQueueFamilyIndex;
  		VK_QUEUE_FAMILY_IGNORED,						//uint32_t					dstQueueFamilyIndex;
  		buffer,											//VkBuffer					buffer;
  		offset,											//VkDeviceSize				offset;
  		size											//VkDeviceSize				size;
  	};
  
  	m_vkd.cmdPipelineBarrier(*m_cmdBufferPrimary, srcStageMask, dstStageMask, DE_FALSE, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
  }
  
  void ConditionalRenderingBaseTestInstance::prepareReferenceImageOneColor (tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColor)
  {
  	for (int w = 0; w < WIDTH; ++w)
  		for (int h = 0; h < HEIGHT; ++h)
  			reference.setPixel(tcu::Vec4(clearColor.float32[0], clearColor.float32[1], clearColor.float32[2], clearColor.float32[3]), w, h);
  }
  
  void ConditionalRenderingBaseTestInstance::prepareReferenceImageOneColor (tcu::PixelBufferAccess& reference, const tcu::Vec4& color)
  {
  	for (int w = 0; w < WIDTH; ++w)
  		for (int h = 0; h < HEIGHT; ++h)
  			reference.setPixel(tcu::Vec4(color), w, h);
  }
  
  void ConditionalRenderingBaseTestInstance::prepareReferenceImageOneDepth (tcu::PixelBufferAccess& reference, const VkClearDepthStencilValue& clearValue)
  {
  	for (int w = 0; w < WIDTH; ++w)
  		for (int h = 0; h < HEIGHT; ++h)
  			reference.setPixDepth(clearValue.depth, w, h);
  }
  
  void ConditionalRenderingBaseTestInstance::prepareReferenceImageDepthClearPartial (tcu::PixelBufferAccess& reference, const VkClearDepthStencilValue& clearValueInitial, const VkClearDepthStencilValue& clearValueFinal)
  {
  	for (int w = 0; w < WIDTH; ++w)
  		for (int h = 0; h < HEIGHT; ++h)
  		{
  			if
  				(w >= (WIDTH / 2) && h >= (HEIGHT / 2)) reference.setPixDepth(clearValueFinal.depth, w, h);
  			else
  				reference.setPixDepth(clearValueInitial.depth, w, h);
  		}
  }
  
  void ConditionalRenderingBaseTestInstance::prepareReferenceImageColorClearPartial (tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColorInitial, const VkClearColorValue& clearColorFinal)
  {
  	for (int w = 0; w < WIDTH; ++w)
  		for (int h = 0; h < HEIGHT; ++h)
  		{
  			if
  				(w >= (WIDTH / 2) && h >= (HEIGHT / 2)) reference.setPixel(tcu::Vec4(clearColorFinal.float32[0], clearColorFinal.float32[1], clearColorFinal.float32[2], clearColorFinal.float32[3]), w, h);
  			else
  				reference.setPixel(tcu::Vec4(clearColorInitial.float32[0], clearColorInitial.float32[1], clearColorInitial.float32[2], clearColorInitial.float32[3]), w, h);
  		}
  }
  
  void ConditionalRenderingBaseTestInstance::clearWithClearColorImage (const VkClearColorValue& color)
  {
  	const struct VkImageSubresourceRange	subRangeColor =
  	{
  		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags		aspectMask
  		0u,							// deUint32					baseMipLevel
  		1u,							// deUint32					mipLevels
  		0u,							// deUint32					baseArrayLayer
  		1u,							// deUint32					arraySize
  	};
  	m_vkd.cmdClearColorImage(*m_cmdBufferPrimary, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &color, 1, &subRangeColor);
  }
  
  void ConditionalRenderingBaseTestInstance::clearWithClearDepthStencilImage (const VkClearDepthStencilValue& value)
  {
  	const struct VkImageSubresourceRange	subRangeColor =
  	{
  		VK_IMAGE_ASPECT_DEPTH_BIT,	// VkImageAspectFlags	aspectMask
  		0u,							// deUint32				baseMipLevel
  		1u,							// deUint32				mipLevels
  		0u,							// deUint32				baseArrayLayer
  		1u,							// deUint32				arraySize
  	};
  	m_vkd.cmdClearDepthStencilImage(*m_cmdBufferPrimary, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &value, 1, &subRangeColor);
  }
  
  void ConditionalRenderingBaseTestInstance::clearColorWithClearAttachments (const VkClearColorValue& color, bool partial)
  {
  	const VkClearAttachment		clearAttachment =
  	{
  		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags		aspectMask;
  		0u,							// deUint32					colorAttachment;
  		{ color }					// VkClearValue				clearValue;
  	};
  	VkRect2D					renderArea			= { { 0, 0 },{ WIDTH, HEIGHT } };
  
  	if (partial)
  	{
  		renderArea.offset.x = WIDTH / 2;
  		renderArea.offset.y = HEIGHT / 2;
  		renderArea.extent.width = WIDTH / 2;
  		renderArea.extent.height = HEIGHT / 2;
  	}
  
  	const VkClearRect			clearRect =
  	{
  		renderArea,					// VkRect2D					rect;
  		0u,							// deUint32					baseArrayLayer;
  		1u							// deUint32					layerCount;
  	};
  
  	m_vkd.cmdClearAttachments(*m_cmdBufferPrimary, 1, &clearAttachment, 1, &clearRect);
  }
  
  void ConditionalRenderingBaseTestInstance::clearDepthWithClearAttachments (const VkClearDepthStencilValue& depthStencil, bool partial)
  {
  	const VkClearAttachment clearAttachment =
  	{
  		VK_IMAGE_ASPECT_DEPTH_BIT,												// VkImageAspectFlags		aspectMask;
  		0u,																		// deUint32					colorAttachment;
  		makeClearValueDepthStencil(depthStencil.depth, depthStencil.stencil)	// VkClearValue				clearValue;
  	};
  	VkRect2D				renderArea			= { { 0, 0 },{ WIDTH, HEIGHT } };
  
  	if (partial)
  	{
  		renderArea.offset.x = WIDTH / 2;
  		renderArea.offset.y = HEIGHT / 2;
  		renderArea.extent.width = WIDTH / 2;
  		renderArea.extent.height = HEIGHT / 2;
  	}
  
  	const VkClearRect		clearRect =
  	{
  		renderArea,																// VkRect2D					rect;
  		0u,																		// deUint32					baseArrayLayer;
  		1u																		// deUint32					layerCount;
  	};
  	m_vkd.cmdClearAttachments(*m_cmdBufferPrimary, 1, &clearAttachment, 1, &clearRect);
  }
  
  void ConditionalRenderingBaseTestInstance::createResultBuffer (VkFormat format)
  {
  	VkDeviceSize		size	= WIDTH * HEIGHT * mapVkFormat(format).getPixelSize();
  	m_resultBuffer				= Buffer::createAndAlloc(m_vkd, m_device, BufferCreateInfo(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
  }
  
  void ConditionalRenderingBaseTestInstance::createVertexBuffer (void)
  {
  	float triangleData[]							= {	-1.0f,		-1.0f,		0.0f,	1.0f,
  														-1.0f,		1.0f,		0.0f,	1.0f,
  														1.0f,		1.0f,		0.0f,	1.0f,
  														1.0f,		-1.0f,		0.0f,	1.0f };
  
  	m_vertexBuffer									= Buffer::createAndAlloc(m_vkd, m_device, BufferCreateInfo(sizeof(triangleData), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
  
  	void * vertexBufferDataPointer					= m_vertexBuffer->getBoundMemory().getHostPtr();
  
  	deMemcpy(vertexBufferDataPointer, triangleData, sizeof(triangleData));
  	flushMappedMemoryRange(m_vkd, m_device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
  }
  
  void ConditionalRenderingBaseTestInstance::createPipelineLayout (void)
  {
  	const VkPipelineLayoutCreateInfo	pipelineLayoutParams =
  	{
  		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType
  		DE_NULL,										// const void*					pNext
  		(VkPipelineLayoutCreateFlags)0,					// VkPipelineLayoutCreateFlags	flags
  		1u,												// deUint32						descriptorSetCount
  		&(m_descriptorSetLayout.get()),					// const VkDescriptorSetLayout*	pSetLayouts
  		0u,												// deUint32						pushConstantRangeCount
  		DE_NULL											// const VkPushConstantRange*	pPushConstantRanges
  	};
  
  	m_pipelineLayout					= vk::createPipelineLayout(m_vkd, m_device, &pipelineLayoutParams);
  }
  
  void ConditionalRenderingBaseTestInstance::createAndUpdateDescriptorSet (void)
  {
  	const VkDescriptorSetAllocateInfo	allocInfo =
  	{
  		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// VkStructureType								sType
  		DE_NULL,												// const void*									pNext
  		*m_descriptorPool,										// VkDescriptorPool								descriptorPool
  		1u,														// deUint32										setLayoutCount
  		&(m_descriptorSetLayout.get())							// const VkDescriptorSetLayout*					pSetLayouts
  	};
  
  	m_descriptorSet						= allocateDescriptorSet(m_vkd, m_device, &allocInfo);
  	VkDescriptorBufferInfo				descriptorInfo			= makeDescriptorBufferInfo(m_vertexBuffer->object(), (VkDeviceSize)0u, sizeof(float) * 16);
  
  	DescriptorSetUpdateBuilder()
  		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
  		.update(m_vkd, m_device);
  }
  
  void ConditionalRenderingBaseTestInstance::createPipeline (void)
  {
  	const std::vector<VkViewport>					viewports(1, makeViewport(tcu::UVec2(WIDTH, HEIGHT)));
  	const std::vector<VkRect2D>						scissors(1, makeRect2D(tcu::UVec2(WIDTH, HEIGHT)));
  	const VkPrimitiveTopology						topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
  	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams =
  	{
  		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,										// VkStructureType								sType
  		DE_NULL,																						// const void*									pNext
  		0u,																								// vkPipelineVertexInputStateCreateFlags		flags
  		0u,																								// deUint32										bindingCount
  		DE_NULL,																						// const VkVertexInputBindingDescription*		pVertexBindingDescriptions
  		0u,																								// deUint32										attributeCount
  		DE_NULL,																						// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
  	};
  
  	m_pipeline										= makeGraphicsPipeline(m_vkd,						// const DeviceInterface&						vk
  																		   m_device,					// const VkDevice								device
  																		   *m_pipelineLayout,			// const VkPipelineLayout						pipelineLayout
  																		   *m_vertexShaderModule,		// const VkShaderModule							vertexShaderModule
  																		   DE_NULL,						// const VkShaderModule							tessellationControlShaderModule
  																		   DE_NULL,						// const VkShaderModule							tessellationEvalShaderModule
  																		   DE_NULL,						// const VkShaderModule							geometryShaderModule
  																		   *m_fragmentShaderModule,		// const VkShaderModule							fragmentShaderModule
  																		   *m_renderPass,				// const VkRenderPass							renderPass
  																		   viewports,					// const std::vector<VkViewport>&				viewports
  																		   scissors,					// const std::vector<VkRect2D>&					scissors
  																		   topology,					// const VkPrimitiveTopology					topology
  																		   0u,							// const deUint32								subpass
  																		   0u,							// const deUint32								patchControlPoints
  																		   &vertexInputStateParams);	// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
  }
  
  void ConditionalRenderingBaseTestInstance::copyResultImageToBuffer (VkImageAspectFlags imageAspectFlags, VkImage image)
  {
  	const VkBufferImageCopy region_all =
  	{
  		0,												// VkDeviceSize					bufferOffset
  		0,												// deUint32						bufferRowLength
  		0,												// deUint32						bufferImageHeight
  		{ imageAspectFlags, 0, 0, 1 },					// VkImageSubresourceLayers		imageSubresource
  		{ 0, 0, 0 },									// VkOffset3D					imageOffset
  		{ WIDTH, HEIGHT, 1 }							// VkExtent3D					imageExtent
  	};
  
  	m_vkd.cmdCopyImageToBuffer(*m_cmdBufferPrimary, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_resultBuffer->object(), 1, &region_all);
  }
  
  void ConditionalRenderingBaseTestInstance::draw (void)
  {
  	m_vkd.cmdDraw(*m_cmdBufferPrimary, 4, 1, 0, 0);
  }
  
  ConditionalRenderingClearAttachmentsTestInstance::ConditionalRenderingClearAttachmentsTestInstance (Context& context, const ClearTestParams& testParams)
  	: ConditionalRenderingBaseTestInstance	(context)
  	, m_testParams							(testParams)
  {}
  
  tcu::TestStatus ConditionalRenderingClearAttachmentsTestInstance::iterate (void)
  {
  	const deUint32								queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
  	deUint32									offsetMultiplier		= 0;
  	VkClearColorValue							clearColorInitial		= { { 0.0f, 0.0f, 1.0f, 1.0f } };
  	VkClearColorValue							clearColorMiddle		= { { 1.0f, 0.0f, 0.0f, 1.0f } };
  	VkClearColorValue							clearColorFinal			= { { 0.0f, 1.0f, 0.0f, 1.0f } };
  	VkClearDepthStencilValue					clearDepthValueInitial	= { 0.4f, 0 };
  	VkClearDepthStencilValue					clearDepthValueMiddle	= { 0.6f, 0 };
  	VkClearDepthStencilValue					clearDepthValueFinal	= { 0.9f, 0 };
  
  	if (m_testParams.m_useOffset) offsetMultiplier = 3;
  
  	createInitBufferWithPredicate(m_testParams.m_discard, m_testParams.m_invert, offsetMultiplier);
  	m_testParams.m_testDepth ? createTargetDepthImageAndImageView() : createTargetColorImageAndImageView();
  	createResultBuffer(m_testParams.m_testDepth ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM);
  
  	m_cmdPool									= createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
  	m_cmdBufferPrimary							= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
  
  	createRenderPass(m_testParams.m_testDepth ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM, m_testParams.m_testDepth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  	createFramebuffer(m_testParams.m_testDepth ? m_depthTargetView.get() : m_colorTargetView.get());
  
  	const VkConditionalRenderingBeginInfoEXT	conditionalRenderingBeginInfo =
  	{
  		VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT,																						//VkStructureType					sType;
  		DE_NULL,																																	//const void*						pNext;
  		m_conditionalRenderingBuffer->object(),																										//VkBuffer							buffer;
  		sizeof(deUint32) * offsetMultiplier,																										//VkDeviceSize						offset;
  		(m_testParams.m_invert ? (VkConditionalRenderingFlagsEXT) VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : (VkConditionalRenderingFlagsEXT) 0)	//VkConditionalRenderingFlagsEXT	flags;
  	};
  
  	beginCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	imageMemoryBarrier(m_testParams.m_testDepth ? m_depthTargetImage->object() : m_colorTargetImage->object(),										//VkImage							 image
  					   0u,																															//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																								//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_UNDEFINED,																									//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																						//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																								//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																								//VkPipelineStageFlags				dstStageMask
  					   m_testParams.m_testDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT);											//VkImageAspectFlags				flags
  
  	m_testParams.m_testDepth					?	clearWithClearDepthStencilImage(clearDepthValueInitial)
  												:	clearWithClearColorImage(clearColorInitial);
  
  	imageMemoryBarrier(m_testParams.m_testDepth ? m_depthTargetImage->object() : m_colorTargetImage->object(),										//VkImage							image
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																								//VkAccessFlags						srcAccessMask
  					   m_testParams.m_testDepth ? (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
  												: (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),						//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																						//VkImageLayout						oldLayout
  					   m_testParams.m_testDepth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																								//VkPipelineStageFlags				srcStageMask
  					   m_testParams.m_testDepth ? VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,				//VkPipelineStageFlags				dstStageMask
  					   m_testParams.m_testDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT);											//VkImageAspectFlags				flags
  
  	if (m_testParams.m_clearAttachmentTwice)
  	{
  		beginRenderPass(m_vkd, *m_cmdBufferPrimary, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
  
  		m_testParams.m_testDepth	? clearDepthWithClearAttachments(clearDepthValueMiddle, m_testParams.m_partialClear)
  									: clearColorWithClearAttachments(clearColorMiddle, m_testParams.m_partialClear);
  
  		m_vkd.cmdBeginConditionalRenderingEXT(*m_cmdBufferPrimary, &conditionalRenderingBeginInfo);
  
  		m_testParams.m_testDepth	? clearDepthWithClearAttachments(clearDepthValueFinal, m_testParams.m_partialClear)
  									: clearColorWithClearAttachments(clearColorFinal, m_testParams.m_partialClear);
  
  		m_vkd.cmdEndConditionalRenderingEXT(*m_cmdBufferPrimary);
  
  		endRenderPass(m_vkd, *m_cmdBufferPrimary);
  	}
  	else
  	{
  		m_vkd.cmdBeginConditionalRenderingEXT(*m_cmdBufferPrimary, &conditionalRenderingBeginInfo);
  
  		beginRenderPass(m_vkd, *m_cmdBufferPrimary, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
  
  		m_testParams.m_testDepth	?	clearDepthWithClearAttachments(clearDepthValueFinal, m_testParams.m_partialClear)
  									:	clearColorWithClearAttachments(clearColorFinal, m_testParams.m_partialClear);
  
  		endRenderPass(m_vkd, *m_cmdBufferPrimary);
  		m_vkd.cmdEndConditionalRenderingEXT(*m_cmdBufferPrimary);
  	}
  
  	imageMemoryBarrier(m_testParams.m_testDepth ? m_depthTargetImage->object() : m_colorTargetImage->object(),										//VkImage							image
  					   m_testParams.m_testDepth ? (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT)
  												: (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),						//VkAccessFlags						dstAccessMask
  					   VK_ACCESS_TRANSFER_READ_BIT,																									//VkAccessFlags						dstAccessMask
  					   m_testParams.m_testDepth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,																						//VkImageLayout						newLayout
  					   m_testParams.m_testDepth ? VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,				//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																								//VkPipelineStageFlags				dstStageMask
  					   m_testParams.m_testDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT);											//VkImageAspectFlags				flags
  
  	copyResultImageToBuffer(m_testParams.m_testDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT, m_testParams.m_testDepth ? m_depthTargetImage->object() : m_colorTargetImage->object());
  
  	const vk::VkBufferMemoryBarrier bufferMemoryBarrier =
  	{
  		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
  		DE_NULL,
  		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
  		vk::VK_ACCESS_HOST_READ_BIT,
  		VK_QUEUE_FAMILY_IGNORED,
  		VK_QUEUE_FAMILY_IGNORED,
  		m_resultBuffer->object(),
  		0u,
  		VK_WHOLE_SIZE
  	};
  
  	m_vkd.cmdPipelineBarrier(*m_cmdBufferPrimary, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferMemoryBarrier, 0u, DE_NULL);
  
  	endCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	submitCommandsAndWait(m_vkd, m_device, m_queue, *m_cmdBufferPrimary);
  
  	invalidateMappedMemoryRange(m_vkd, m_device, m_resultBuffer->getBoundMemory().getMemory(), m_resultBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
  
  	tcu::ConstPixelBufferAccess					result(mapVkFormat(m_testParams.m_testDepth ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), m_resultBuffer->getBoundMemory().getHostPtr());
  
  	std::vector<float>							referenceData((m_testParams.m_testDepth ? 1 : 4) * WIDTH * HEIGHT, 0);
  	tcu::PixelBufferAccess						reference(mapVkFormat(m_testParams.m_testDepth ? VK_FORMAT_D32_SFLOAT : VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), referenceData.data());
  
  	if (!m_testParams.m_partialClear)
  	{
  		m_testParams.m_testDepth	? prepareReferenceImageOneDepth(reference, m_testParams.m_discard ? (m_testParams.m_clearAttachmentTwice ? clearDepthValueMiddle : clearDepthValueInitial) : clearDepthValueFinal)
  									: prepareReferenceImageOneColor(reference, m_testParams.m_discard ? (m_testParams.m_clearAttachmentTwice ? clearColorMiddle : clearColorInitial) : clearColorFinal);
  	}
  	else
  	{
  		m_testParams.m_testDepth	? prepareReferenceImageDepthClearPartial(reference, clearDepthValueInitial, m_testParams.m_discard ? (m_testParams.m_clearAttachmentTwice ? clearDepthValueMiddle : clearDepthValueInitial) : clearDepthValueFinal)
  									: prepareReferenceImageColorClearPartial(reference, clearColorInitial, m_testParams.m_discard ? (m_testParams.m_clearAttachmentTwice ? clearColorMiddle : clearColorInitial) : clearColorFinal);
  	}
  
  	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
  		return tcu::TestStatus::fail("Fail");
  
  	return tcu::TestStatus::pass("Pass");
  }
  
  ConditionalRenderingDrawTestInstance::ConditionalRenderingDrawTestInstance (Context& context, const DrawTestParams& testParams)
  	: ConditionalRenderingBaseTestInstance	(context)
  	, m_testParams							(testParams)
  {}
  
  tcu::TestStatus ConditionalRenderingDrawTestInstance::iterate (void)
  {
  	const deUint32						queueFamilyIndex				= m_context.getUniversalQueueFamilyIndex();
  	VkClearColorValue					clearColorInitial				= { { 0.0f, 0.0f, 1.0f, 1.0f } };
  	deUint32							offsetMultiplier				= 0;
  
  	if (m_testParams.m_useOffset) offsetMultiplier = 3;
  
  	VkBufferUsageFlagBits				bufferUsageExtraFlags			= (VkBufferUsageFlagBits)0;
  	if (m_testParams.m_togglePredicate)
  		bufferUsageExtraFlags = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
  	createInitBufferWithPredicate(m_testParams.m_discard, m_testParams.m_invert, offsetMultiplier, bufferUsageExtraFlags);
  
  	if (m_testParams.m_toggleMode == COPY)
  	{
  		//we need another buffer to copy from, with toggled predicate value
  		m_conditionalRenderingBufferForCopy.swap(m_conditionalRenderingBuffer);
  		createInitBufferWithPredicate(!m_testParams.m_discard, m_testParams.m_invert, offsetMultiplier, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
  		m_conditionalRenderingBufferForCopy.swap(m_conditionalRenderingBuffer);
  	}
  	createTargetColorImageAndImageView();
  	createResultBuffer(VK_FORMAT_R8G8B8A8_UNORM);
  	createVertexBuffer();
  
  	m_cmdPool							= createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
  	m_cmdBufferPrimary					= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
  
  	createRenderPass(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  	createFramebuffer(m_colorTargetView.get());
  
  	DescriptorSetLayoutBuilder			builder;
  
  	builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
  
  	m_descriptorSetLayout				= builder.build(m_vkd, m_device, (VkDescriptorSetLayoutCreateFlags)0);
  
  	m_descriptorPool					= DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
  																 .build(m_vkd, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
  
  	createPipelineLayout();
  	createAndUpdateDescriptorSet();
  
  	m_vertexShaderModule				= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("position_only.vert"), 0);
  	m_fragmentShaderModule				= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("only_color_out.frag"), 0);
  
  	createPipeline();
  
  	VkConditionalRenderingBeginInfoEXT	conditionalRenderingBeginInfo =
  	{
  		VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT,																		//VkStructureType					sType;
  		DE_NULL,																													//const void*						pNext;
  		m_conditionalRenderingBuffer->object(),																						//VkBuffer							buffer;
  		sizeof(deUint32) * offsetMultiplier,																						//VkDeviceSize						offset;
  		(m_testParams.m_invert	? (VkConditionalRenderingFlagsEXT)VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT
  								: (VkConditionalRenderingFlagsEXT)0)																//VkConditionalRenderingFlagsEXT	flags;
  	};
  
  	beginCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   0u,																											//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																				//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_UNDEFINED,																					//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																		//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	clearWithClearColorImage(clearColorInitial);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																				//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																		//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,																	//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,																//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	m_vkd.cmdBindPipeline(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
  	m_vkd.cmdBindDescriptorSets(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
  
  	if (m_testParams.m_togglePredicate)
  	{
  		if (m_testParams.m_toggleMode == FILL)
  		{
  			m_testParams.m_discard		= !m_testParams.m_discard;
  			deUint32 predicate			= m_testParams.m_discard ? m_testParams.m_invert : !m_testParams.m_invert;
  			m_vkd.cmdFillBuffer(*m_cmdBufferPrimary, m_conditionalRenderingBuffer->object(), m_conditionalRenderingBufferOffset, sizeof(predicate), predicate);
  			bufferMemoryBarrier(m_conditionalRenderingBuffer->object(), m_conditionalRenderingBufferOffset, sizeof(predicate), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
  								VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT);
  		}
  		if (m_testParams.m_toggleMode == COPY)
  		{
  			VkBufferCopy region =
  			{
  				m_conditionalRenderingBufferOffset,																					//VkDeviceSize						srcOffset;
  				m_conditionalRenderingBufferOffset,																					//VkDeviceSize						dstOffset;
  				sizeof(deUint32)																									//VkDeviceSize						size;
  			};
  			m_vkd.cmdCopyBuffer(*m_cmdBufferPrimary, m_conditionalRenderingBufferForCopy->object(), m_conditionalRenderingBuffer->object(), 1, &region);
  			bufferMemoryBarrier(m_conditionalRenderingBuffer->object(), m_conditionalRenderingBufferOffset, sizeof(deUint32), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
  								VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT);
  		}
  	}
  
  	beginRenderPass(m_vkd, *m_cmdBufferPrimary, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
  
  	deInt32								data[4]							= { -1, -1, -1, -1 };
  	void*								dataPtr							= data;
  
  	for (int drawNdx = 0; drawNdx < 4; drawNdx++)
  	{
  		data[0] = drawNdx;
  		m_vkd.cmdPushConstants(*m_cmdBufferPrimary, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, dataPtr);
  
  		if (isBitSet(m_testParams.m_beginSequenceBits, drawNdx))
  			m_vkd.cmdBeginConditionalRenderingEXT(*m_cmdBufferPrimary, &conditionalRenderingBeginInfo);
  
  		draw();
  
  		if (isBitSet(m_testParams.m_endSequenceBits, drawNdx))
  			m_vkd.cmdEndConditionalRenderingEXT(*m_cmdBufferPrimary);
  	}
  
  	endRenderPass(m_vkd, *m_cmdBufferPrimary);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,																		//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_TRANSFER_READ_BIT,																					//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,																	//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,																		//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,																//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	copyResultImageToBuffer(VK_IMAGE_ASPECT_COLOR_BIT, m_colorTargetImage->object());
  
  	const vk::VkBufferMemoryBarrier bufferMemoryBarrier =
  	{
  		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
  		DE_NULL,
  		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
  		vk::VK_ACCESS_HOST_READ_BIT,
  		VK_QUEUE_FAMILY_IGNORED,
  		VK_QUEUE_FAMILY_IGNORED,
  		m_resultBuffer->object(),
  		0u,
  		VK_WHOLE_SIZE
  	};
  
  	m_vkd.cmdPipelineBarrier(*m_cmdBufferPrimary, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferMemoryBarrier, 0u, DE_NULL);
  
  	endCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	submitCommandsAndWait(m_vkd, m_device, m_queue, *m_cmdBufferPrimary);
  
  	invalidateMappedMemoryRange(m_vkd, m_device, m_resultBuffer->getBoundMemory().getMemory(), m_resultBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
  
  	tcu::ConstPixelBufferAccess			result(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), m_resultBuffer->getBoundMemory().getHostPtr());
  
  	std::vector<float>					referenceData(4 * WIDTH * HEIGHT, 0.5f);
  	tcu::PixelBufferAccess				reference(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), referenceData.data());
  
  	prepareReferenceImage(reference, clearColorInitial, m_testParams.m_resultBits);
  
  	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
  		return tcu::TestStatus::fail("Fail");
  
  	return tcu::TestStatus::pass("Pass");
  }
  
  void ConditionalRenderingDrawTestInstance::createPipelineLayout (void)
  {
  	const VkPushConstantRange			pushConstantRange =
  	{
  		VK_SHADER_STAGE_FRAGMENT_BIT,					//VkShaderStageFlags			stageFlags;
  		0,												//deUint32						offset;
  		16												//deUint32						size;
  	};
  
  	const VkPipelineLayoutCreateInfo	pipelineLayoutParams =
  	{
  		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//VkStructureType				sType
  		DE_NULL,										//const void*					pNext
  		(VkPipelineLayoutCreateFlags)0,					//VkPipelineLayoutCreateFlags	flags
  		1u,												//deUint32						descriptorSetCount
  		&(m_descriptorSetLayout.get()),					//const VkDescriptorSetLayout*	pSetLayouts
  		1u,												//deUint32						pushConstantRangeCount
  		&pushConstantRange								//const VkPushConstantRange*	pPushConstantRanges
  	};
  
  	m_pipelineLayout					= vk::createPipelineLayout(m_vkd, m_device, &pipelineLayoutParams);
  }
  
  void ConditionalRenderingDrawTestInstance::prepareReferenceImage (tcu::PixelBufferAccess& reference, const VkClearColorValue& clearColor, deUint32 resultBits)
  {
  	for (int w = 0; w < WIDTH; w++)
  		for (int h = 0; h < HEIGHT; h++)
  			reference.setPixel(tcu::Vec4(clearColor.float32), w, h);
  
  	int step = (HEIGHT / 4);
  	for (int w = 0; w < WIDTH; w++)
  		for (int h = 0; h < HEIGHT; h++)
  		{
  			if (h < step && isBitSet(resultBits, 0)) reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
  			if (h >= step && h < (step * 2) && isBitSet(resultBits, 1)) reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
  			if (h >= (step * 2) && h < (step * 3) && isBitSet(resultBits, 2)) reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
  			if (h >= (step * 3) && isBitSet(resultBits, 3)) reference.setPixel(tcu::Vec4(0, 1, 0, 1), w, h);
  		}
  }
  
  ConditionalRenderingUpdateBufferWithDrawTestInstance::ConditionalRenderingUpdateBufferWithDrawTestInstance (Context& context, bool testParams)
  	: ConditionalRenderingBaseTestInstance	(context)
  	, m_testParams							(testParams)
  {}
  
  void ConditionalRenderingUpdateBufferWithDrawTestInstance::createAndUpdateDescriptorSets (void)
  {
  	//the same descriptor set layout can be used for the creation of both descriptor sets
  	const VkDescriptorSetAllocateInfo	allocInfo =
  	{
  		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			//VkStructureType						sType
  		DE_NULL,												//const void*							pNext
  		*m_descriptorPool,										//VkDescriptorPool						descriptorPool
  		1u,														//deUint32								setLayoutCount
  		&(m_descriptorSetLayout.get())							//const VkDescriptorSetLayout*			pSetLayouts
  	};
  
  	m_descriptorSet						= allocateDescriptorSet(m_vkd, m_device, &allocInfo);
  	VkDescriptorBufferInfo				descriptorInfo			= makeDescriptorBufferInfo(m_vertexBuffer->object(), (VkDeviceSize)0u, sizeof(float) * 16);
  
  	DescriptorSetUpdateBuilder()
  		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
  		.update(m_vkd, m_device);
  
  	m_descriptorSetUpdate				= allocateDescriptorSet(m_vkd, m_device, &allocInfo);
  	VkDescriptorBufferInfo				descriptorInfoUpdate	= makeDescriptorBufferInfo(m_conditionalRenderingBuffer->object(), (VkDeviceSize)0u, sizeof(deUint32));
  
  	DescriptorSetUpdateBuilder()
  		.writeSingle(*m_descriptorSetUpdate, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfoUpdate)
  		.update(m_vkd, m_device);
  }
  
  void ConditionalRenderingUpdateBufferWithDrawTestInstance::createPipelines (void)
  {
  	const std::vector<VkViewport>					viewports(1, makeViewport(tcu::UVec2(WIDTH, HEIGHT)));
  	const std::vector<VkRect2D>						scissors(1, makeRect2D(tcu::UVec2(WIDTH, HEIGHT)));
  	const VkPrimitiveTopology						topology														= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
  	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams =
  	{
  		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,													//VkStructureType								sType
  		DE_NULL,																									//const void*									pNext
  		0u,																											//vkPipelineVertexInputStateCreateFlags			flags
  		0u,																											//deUint32										bindingCount
  		DE_NULL,																									//const VkVertexInputBindingDescription*		pVertexBindingDescriptions
  		0u,																											//deUint32										attributeCount
  		DE_NULL,																									//const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
  	};
  
  	m_pipelineDraw									= makeGraphicsPipeline(m_vkd,									//const DeviceInterface&						vk
  																		   m_device,								//const VkDevice								device
  																		   *m_pipelineLayout,						//const VkPipelineLayout						pipelineLayout
  																		   *m_vertexShaderModuleDraw,				//const VkShaderModule							vertexShaderModule
  																		   DE_NULL,									//const VkShaderModule							tessellationControlShaderModule
  																		   DE_NULL,									//const VkShaderModule							tessellationEvalShaderModule
  																		   DE_NULL,									//const VkShaderModule							geometryShaderModule
  																		   *m_fragmentShaderModuleDraw,				//const VkShaderModule							fragmentShaderModule
  																		   *m_renderPass,							//const VkRenderPass							renderPass
  																		   viewports,								//const std::vector<VkViewport>&				viewports
  																		   scissors,								//const std::vector<VkRect2D>&					scissors
  																		   topology,								//const VkPrimitiveTopology						topology
  																		   0u,										//const deUint32								subpass
  																		   0u,										//const deUint32								patchControlPoints
  																		   &vertexInputStateParams);				//const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
  
  	m_pipelineUpdate								= makeGraphicsPipeline(m_vkd,									//const DeviceInterface&						vk
  																		   m_device,								//const VkDevice								device
  																		   *m_pipelineLayout,						//const VkPipelineLayout						pipelineLayout
  																		   *m_vertexShaderModuleUpdate,				//const VkShaderModule							vertexShaderModule
  																		   DE_NULL,									//const VkShaderModule							tessellationControlShaderModule
  																		   DE_NULL,									//const VkShaderModule							tessellationEvalShaderModule
  																		   DE_NULL,									//const VkShaderModule							geometryShaderModule
  																		   *m_fragmentShaderModuleDiscard,			//const VkShaderModule							fragmentShaderModule
  																		   *m_renderPass,							//const VkRenderPass							renderPass
  																		   viewports,								//const std::vector<VkViewport>&				viewports
  																		   scissors,								//const std::vector<VkRect2D>&					scissors
  																		   topology,								//const VkPrimitiveTopology						topology
  																		   0u,										//const deUint32								subpass
  																		   0u,										//const deUint32								patchControlPoints
  																		   &vertexInputStateParams);				//const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
  }
  
  void ConditionalRenderingUpdateBufferWithDrawTestInstance::createRenderPass (VkFormat format, VkImageLayout layout)
  {
  	RenderPassCreateInfo			renderPassCreateInfo;
  
  	renderPassCreateInfo.addAttachment(AttachmentDescription(format,
  															 VK_SAMPLE_COUNT_1_BIT,
  															 VK_ATTACHMENT_LOAD_OP_LOAD,
  															 VK_ATTACHMENT_STORE_OP_STORE,
  															 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
  															 VK_ATTACHMENT_STORE_OP_STORE,
  															 isDepthStencilFormat(format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
  															 isDepthStencilFormat(format) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
  
  	const VkAttachmentReference		attachmentReference =
  	{
  		0u,														// deUint32				attachment
  		layout													// VkImageLayout		layout
  	};
  
  	renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
  													   0,
  													   0,
  													   DE_NULL,
  													   isDepthStencilFormat(format) ? 0 : 1,
  													   isDepthStencilFormat(format) ? DE_NULL : &attachmentReference,
  													   DE_NULL,
  													   isDepthStencilFormat(format) ? attachmentReference : AttachmentReference(),
  													   0,
  													   DE_NULL));
  
  	VkSubpassDependency				dependency =
  	{
  		0,														//deUint32				srcSubpass;
  		0,														//deUint32				dstSubpass;
  		VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,					//VkPipelineStageFlags	srcStageMask;
  		VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,		//VkPipelineStageFlags	dstStageMask;
  		VK_ACCESS_SHADER_WRITE_BIT,								//VkAccessFlags			srcAccessMask;
  		VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,			//VkAccessFlags			dstAccessMask;
  		(VkDependencyFlags)0									//VkDependencyFlags		dependencyFlags;
  	};
  
  	renderPassCreateInfo.addDependency(dependency);
  
  	m_renderPass					= vk::createRenderPass(m_vkd, m_device, &renderPassCreateInfo);
  }
  
  tcu::TestStatus ConditionalRenderingUpdateBufferWithDrawTestInstance::iterate (void)
  {
  	const deUint32							queueFamilyIndex						= m_context.getUniversalQueueFamilyIndex();
  	VkClearColorValue						clearColorInitial						= { { 0.0f, 0.0f, 1.0f, 1.0f } };
  
  	createInitBufferWithPredicate(m_testParams, true, 0, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
  
  	createTargetColorImageAndImageView();
  	createResultBuffer(VK_FORMAT_R8G8B8A8_UNORM);
  	createVertexBuffer();
  
  	m_cmdPool								= createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
  	m_cmdBufferPrimary						= allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
  
  	createRenderPass(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  	createFramebuffer(m_colorTargetView.get());
  
  	DescriptorSetLayoutBuilder				builder;
  	builder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
  	m_descriptorSetLayout					= builder.build(m_vkd, m_device, (VkDescriptorSetLayoutCreateFlags)0);
  
  	m_descriptorPool						= DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2)
  																	 .build(m_vkd, m_device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u);
  
  	createPipelineLayout();
  	createAndUpdateDescriptorSets();
  
  	m_vertexShaderModuleDraw				= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("position_only.vert"), 0);
  	m_fragmentShaderModuleDraw				= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("only_color_out.frag"), 0);
  	m_vertexShaderModuleUpdate				= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("update.vert"), 0);
  	m_fragmentShaderModuleDiscard			= createShaderModule(m_vkd, m_device, m_context.getBinaryCollection().get("discard.frag"), 0);
  
  	createPipelines();
  
  	VkConditionalRenderingBeginInfoEXT		conditionalRenderingBeginInfo =
  	{
  		VK_STRUCTURE_TYPE_CONDITIONAL_RENDERING_BEGIN_INFO_EXT,																		//VkStructureType					sType;
  		DE_NULL,																													//const void*						pNext;
  		m_conditionalRenderingBuffer->object(),																						//VkBuffer							buffer;
  		0,																															//VkDeviceSize						offset;
  		VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT																					//VkConditionalRenderingFlagsEXT	flags;
  	};
  
  	beginCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   0u,																											//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																				//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_UNDEFINED,																					//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																		//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	clearWithClearColorImage(clearColorInitial);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   VK_ACCESS_TRANSFER_WRITE_BIT,																				//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,									//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,																		//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,																	//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,																//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	beginRenderPass(m_vkd, *m_cmdBufferPrimary, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
  
  	m_vkd.cmdBindPipeline(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineUpdate);
  	m_vkd.cmdBindDescriptorSets(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSetUpdate), 0, DE_NULL);
  
  	draw();
  
  	endRenderPass(m_vkd, *m_cmdBufferPrimary);
  
  	bufferMemoryBarrier(m_conditionalRenderingBuffer->object(), m_conditionalRenderingBufferOffset, sizeof(deUint32), VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
  						VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT);
  
  	beginRenderPass(m_vkd, *m_cmdBufferPrimary, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT));
  
  	m_vkd.cmdBindPipeline(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineDraw);
  	m_vkd.cmdBindDescriptorSets(*m_cmdBufferPrimary, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
  
  	m_vkd.cmdBeginConditionalRenderingEXT(*m_cmdBufferPrimary, &conditionalRenderingBeginInfo);
  	draw();
  	m_vkd.cmdEndConditionalRenderingEXT(*m_cmdBufferPrimary);
  
  	endRenderPass(m_vkd, *m_cmdBufferPrimary);
  
  	imageMemoryBarrier(m_colorTargetImage->object(),																				//VkImage							image
  					   VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,																		//VkAccessFlags						srcAccessMask
  					   VK_ACCESS_TRANSFER_READ_BIT,																					//VkAccessFlags						dstAccessMask
  					   VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,																	//VkImageLayout						oldLayout
  					   VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,																		//VkImageLayout						newLayout
  					   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,																//VkPipelineStageFlags				srcStageMask
  					   VK_PIPELINE_STAGE_TRANSFER_BIT,																				//VkPipelineStageFlags				dstStageMask
  					   VK_IMAGE_ASPECT_COLOR_BIT);																					//VkImageAspectFlags				flags
  
  	copyResultImageToBuffer(VK_IMAGE_ASPECT_COLOR_BIT, m_colorTargetImage->object());
  
  	const vk::VkBufferMemoryBarrier bufferMemoryBarrier =
  	{
  		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
  		DE_NULL,
  		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
  		vk::VK_ACCESS_HOST_READ_BIT,
  		VK_QUEUE_FAMILY_IGNORED,
  		VK_QUEUE_FAMILY_IGNORED,
  		m_resultBuffer->object(),
  		0u,
  		VK_WHOLE_SIZE
  	};
  
  	m_vkd.cmdPipelineBarrier(*m_cmdBufferPrimary, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferMemoryBarrier, 0u, DE_NULL);
  
  	endCommandBuffer(m_vkd, *m_cmdBufferPrimary);
  
  	submitCommandsAndWait(m_vkd, m_device, m_queue, *m_cmdBufferPrimary);
  
  	invalidateMappedMemoryRange(m_vkd, m_device, m_resultBuffer->getBoundMemory().getMemory(), m_resultBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
  
  	tcu::ConstPixelBufferAccess			result(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), m_resultBuffer->getBoundMemory().getHostPtr());
  
  	std::vector<float>					referenceData(4 * WIDTH * HEIGHT, 0.0f);
  	tcu::PixelBufferAccess				reference(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), tcu::IVec3(WIDTH, HEIGHT, 1), referenceData.data());
  
  	m_testParams ? prepareReferenceImageOneColor(reference, tcu::Vec4(0,1,0,1)) : prepareReferenceImageOneColor(reference, clearColorInitial);
  
  	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Comparison", "Comparison", reference, result, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
  		return tcu::TestStatus::fail("Fail");
  
  	return tcu::TestStatus::pass("Pass");
  }
  
  struct AddProgramsDraw
  {
  	void init (SourceCollections& sources, DrawTestParams testParams) const
  	{
  		DE_UNREF(testParams);
  
  		const char* const		vertexShader =
  			"#version 430\n"
  
  			"layout(std430, binding = 0) buffer BufferPos {\n"
  			"vec4 p[100];\n"
  			"} pos;\n"
  
  			"out gl_PerVertex{\n"
  			"vec4 gl_Position;\n"
  			"};\n"
  
  			"void main() {\n"
  			"gl_Position = pos.p[gl_VertexIndex];\n"
  			"}\n";
  
  		sources.glslSources.add("position_only.vert") << glu::VertexSource(vertexShader);
  
  		const char* const		fragmentShader =
  			"#version 430\n"
  
  			"layout(location = 0) out vec4 my_FragColor;\n"
  
  			"layout (push_constant) uniform AreaSelect {\n"
  			"	ivec4 number;\n"
  			"} Area;\n"
  
  			"void main() {\n"
  			"	if((gl_FragCoord.y < 64) && (Area.number.x != 0)) discard;\n"
  			"	if((gl_FragCoord.y >= 64) && (gl_FragCoord.y < 128) && (Area.number.x != 1)) discard;\n"
  			"	if((gl_FragCoord.y >= 128) && (gl_FragCoord.y < 192) && (Area.number.x != 2)) discard;\n"
  			"	if((gl_FragCoord.y >= 192) && (Area.number.x != 3)) discard;\n"
  			"	my_FragColor = vec4(0,1,0,1);\n"
  			"}\n";
  
  		sources.glslSources.add("only_color_out.frag") << glu::FragmentSource(fragmentShader);
  	}
  };
  
  struct AddProgramsUpdateBufferUsingRendering
  {
  	void init (SourceCollections& sources, bool testParams) const
  	{
  		std::string				atomicOperation			= (testParams ? "atomicMin(predicate.p, 0);" : "atomicMax(predicate.p, 1);");
  
  		std::string				vertexShaderUpdate =
  			"#version 430\n"
  
  			"layout(std430, binding = 0) buffer Predicate {\n"
  			"uint p;\n"
  			"} predicate;\n"
  
  			"out gl_PerVertex{\n"
  			"vec4 gl_Position;\n"
  			"};\n"
  
  			"void main() {\n" +
  			atomicOperation +
  			"gl_Position = vec4(1.0);\n"
  			"}\n";
  
  		sources.glslSources.add("update.vert") << glu::VertexSource(vertexShaderUpdate);
  
  		const char* const		vertexShaderDraw =
  			"#version 430\n"
  
  			"layout(std430, binding = 0) buffer BufferPos {\n"
  			"vec4 p[100];\n"
  			"} pos;\n"
  
  			"out gl_PerVertex{\n"
  			"vec4 gl_Position;\n"
  			"};\n"
  
  			"void main() {\n"
  			"gl_Position = pos.p[gl_VertexIndex];\n"
  			"}\n";
  
  		sources.glslSources.add("position_only.vert") << glu::VertexSource(vertexShaderDraw);
  
  		const char* const		fragmentShaderDiscard =
  			"#version 430\n"
  
  			"layout(location = 0) out vec4 my_FragColor;\n"
  
  			"void main() {\n"
  			"	discard;\n"
  			"}\n";
  
  		sources.glslSources.add("discard.frag")
  			<< glu::FragmentSource(fragmentShaderDiscard);
  
  		const char* const		fragmentShaderDraw =
  			"#version 430\n"
  
  			"layout(location = 0) out vec4 my_FragColor;\n"
  
  			"void main() {\n"
  			"	my_FragColor = vec4(0,1,0,1);\n"
  			"}\n";
  
  		sources.glslSources.add("only_color_out.frag") << glu::FragmentSource(fragmentShaderDraw);
  	}
  };
  
  void checkSupport (Context& context)
  {
  	context.requireDeviceFunctionality("VK_EXT_conditional_rendering");
  }
  
  void checkFan (Context& context)
  {
  	checkSupport(context);
  
  	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
  		!context.getPortabilitySubsetFeatures().triangleFans)
  	{
  		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
  	}
  }
  
  void checkFanAndVertexStores (Context& context)
  {
  	checkFan(context);
  
  	const auto& features = context.getDeviceFeatures();
  	if (!features.vertexPipelineStoresAndAtomics)
  		TCU_THROW(NotSupportedError, "Vertex pipeline stores and atomics not supported");
  }
  
  } // unnamed namespace
  
  ConditionalRenderingDrawAndClearTests::ConditionalRenderingDrawAndClearTests (tcu::TestContext &testCtx)
  	: TestCaseGroup (testCtx, "draw_clear", "VK_EXT_conditional_rendering extension tests")
  {
  	/* Left blank on purpose */
  }
  
  void ConditionalRenderingDrawAndClearTests::init (void)
  {
  	tcu::TestCaseGroup*	clear	= new tcu::TestCaseGroup(m_testCtx, "clear", "Tests using vkCmdClearAttachments.");
  	tcu::TestCaseGroup*	color	= new tcu::TestCaseGroup(m_testCtx, "color", "Test color clear.");
  	tcu::TestCaseGroup*	depth	= new tcu::TestCaseGroup(m_testCtx, "depth", "Test depth clear.");
  	tcu::TestCaseGroup*	draw	= new tcu::TestCaseGroup(m_testCtx, "draw", "Test drawing.");
  
  	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(clearColorTestGrid); testNdx++)
  		color->addChild(new InstanceFactory1WithSupport<ConditionalRenderingClearAttachmentsTestInstance, ClearTestParams, FunctionSupport0>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, generateClearTestName(clearColorTestGrid[testNdx]), "Color clear test.", clearColorTestGrid[testNdx], checkSupport));
  
  	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(clearDepthTestGrid); testNdx++)
  		depth->addChild(new InstanceFactory1WithSupport<ConditionalRenderingClearAttachmentsTestInstance, ClearTestParams, FunctionSupport0>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, generateClearTestName(clearDepthTestGrid[testNdx]), "Depth clear test.", clearDepthTestGrid[testNdx], checkSupport));
  
  	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(clearColorTwiceGrid); testNdx++)
  		color->addChild(new InstanceFactory1WithSupport<ConditionalRenderingClearAttachmentsTestInstance, ClearTestParams, FunctionSupport0>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, "clear_attachment_twice_" + generateClearTestName(clearColorTwiceGrid[testNdx]), "Color clear test.", clearColorTwiceGrid[testNdx], checkSupport));
  
  	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(clearDepthTwiceGrid); testNdx++)
  		depth->addChild(new InstanceFactory1WithSupport<ConditionalRenderingClearAttachmentsTestInstance, ClearTestParams, FunctionSupport0>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, "clear_attachment_twice_" + generateClearTestName(clearDepthTwiceGrid[testNdx]), "Depth clear test.", clearDepthTwiceGrid[testNdx], checkSupport));
  
  	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(drawTestGrid); testNdx++)
  		draw->addChild(new InstanceFactory1WithSupport<ConditionalRenderingDrawTestInstance, DrawTestParams, FunctionSupport0, AddProgramsDraw>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, "case_" + de::toString(testNdx), "Draw test.", AddProgramsDraw(), drawTestGrid[testNdx], checkFan));
  
  	draw->addChild(new InstanceFactory1WithSupport<ConditionalRenderingUpdateBufferWithDrawTestInstance, bool, FunctionSupport0, AddProgramsUpdateBufferUsingRendering>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, "update_with_rendering_no_discard", "Draw test.", AddProgramsUpdateBufferUsingRendering(), true, checkFanAndVertexStores));
  	draw->addChild(new InstanceFactory1WithSupport<ConditionalRenderingUpdateBufferWithDrawTestInstance, bool, FunctionSupport0, AddProgramsUpdateBufferUsingRendering>(m_testCtx, tcu::NODETYPE_SELF_VALIDATE, "update_with_rendering_discard", "Draw test.", AddProgramsUpdateBufferUsingRendering(), false, checkFanAndVertexStores));
  
  	clear->addChild(color);
  	clear->addChild(depth);
  	addChild(clear);
  	addChild(draw);
  }
  
  } // Draw
  } // vkt
  