Fix RAW and WAW hazards in pipeline barrier tests.

Test was not handling correctly internal state of the visibility and availability operations.
Both access scopes of the barrier must be set correctly to unlock such usage of the resource.

Affects:
dEQP-VK.memory.pipeline_barrier.*

Components: Vulkan
VK-GL-CTS issue: 1589

Change-Id: Ie2b47f160a0181948de1a37d1e7e5202a94d493e
diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp b/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
index 29476ab..8146347 100644
--- a/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
+++ b/external/vulkancts/modules/vulkan/memory/vktMemoryPipelineBarrierTests.cpp
@@ -217,6 +217,34 @@
 	ACCESS_LAST
 };
 
+Access accessFlagToAccess (vk::VkAccessFlagBits flag)
+{
+	switch (flag)
+	{
+	case vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT:			return ACCESS_INDIRECT_COMMAND_READ_BIT;
+	case vk::VK_ACCESS_INDEX_READ_BIT:						return ACCESS_INDEX_READ_BIT;
+	case vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT:			return ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+	case vk::VK_ACCESS_UNIFORM_READ_BIT:					return ACCESS_UNIFORM_READ_BIT;
+	case vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT:			return ACCESS_INPUT_ATTACHMENT_READ_BIT;
+	case vk::VK_ACCESS_SHADER_READ_BIT:						return ACCESS_SHADER_READ_BIT;
+	case vk::VK_ACCESS_SHADER_WRITE_BIT:					return ACCESS_SHADER_WRITE_BIT;
+	case vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT:			return ACCESS_COLOR_ATTACHMENT_READ_BIT;
+	case vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT:			return ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+	case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT:	return ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+	case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT:	return ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+	case vk::VK_ACCESS_TRANSFER_READ_BIT:					return ACCESS_TRANSFER_READ_BIT;
+	case vk::VK_ACCESS_TRANSFER_WRITE_BIT:					return ACCESS_TRANSFER_WRITE_BIT;
+	case vk::VK_ACCESS_HOST_READ_BIT:						return ACCESS_HOST_READ_BIT;
+	case vk::VK_ACCESS_HOST_WRITE_BIT:						return ACCESS_HOST_WRITE_BIT;
+	case vk::VK_ACCESS_MEMORY_READ_BIT:						return ACCESS_MEMORY_READ_BIT;
+	case vk::VK_ACCESS_MEMORY_WRITE_BIT:					return ACCESS_MEMORY_WRITE_BIT;
+
+	default:
+		DE_FATAL("Unknown access flags");
+		return ACCESS_LAST;
+	}
+}
+
 // Sequential stage enums
 enum PipelineStage
 {
@@ -239,9 +267,9 @@
 	PIPELINESTAGE_LAST
 };
 
-PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flags)
+PipelineStage pipelineStageFlagToPipelineStage (vk::VkPipelineStageFlagBits flag)
 {
-	switch (flags)
+	switch (flag)
 	{
 		case vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT:						return PIPELINESTAGE_TOP_OF_PIPE_BIT;
 		case vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT:					return PIPELINESTAGE_BOTTOM_OF_PIPE_BIT;
@@ -7488,9 +7516,9 @@
 	const vk::VkPipelineStageFlags	m_allowedStages;
 	const vk::VkAccessFlags			m_allowedAccesses;
 
-	// [dstStage][srcStage] = srcAccesses
-	// In stage dstStage write srcAccesses from srcStage are not yet available
-	vk::VkAccessFlags				m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+	// [dstStage][srcStage][dstAccess] = srcAccesses
+	// In stage dstStage write srcAccesses from srcStage are not yet available for dstAccess
+	vk::VkAccessFlags				m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
 	// Latest pipeline transition is not available in stage
 	bool							m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
 	// [dstStage] = dstAccesses
@@ -7531,7 +7559,15 @@
 
 			// There are no write operations that are not yet available
 			// initially.
-			m_unavailableWriteOperations[dstStage][srcStage] = 0;
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+			{
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
+			}
 		}
 	}
 }
@@ -7582,8 +7618,16 @@
 			// Mark all accesses from all stages invisible
 			m_invisibleOperations[dstStage] |= m_allowedAccesses;
 
-			// Mark write access from srcStage unavailable to all stages
-			m_unavailableWriteOperations[dstStage][srcStage] |= access;
+			// Mark write access from srcStage unavailable to all stages for all accesses
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+			{
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				m_unavailableWriteOperations[dstStage][srcStage][dstAccess] |= access;
+			}
 		}
 	}
 }
@@ -7643,7 +7687,7 @@
 			dstAccesses |= m_invisibleOperations[dstStage];
 		}
 
-		// Make sure all write operations fro mall stages are available
+		// Make sure all write operations from all stages are available
 		for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
 		{
 			const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
@@ -7651,11 +7695,19 @@
 			if ((srcStage_ & m_allowedStages) == 0)
 				continue;
 
-			if (m_unavailableWriteOperations[dstStage][srcStage])
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
 			{
-				dstStages |= dstStage_;
-				srcStages |= dstStage_;
-				srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess])
+				{
+					dstStages |= dstStage_;
+					srcStages |= dstStage_;
+					srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage][dstAccess];
+				}
 			}
 
 			if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
@@ -7675,9 +7727,9 @@
 }
 
 void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags	srcStages,
-										 vk::VkAccessFlags			srcAccesses,
-										 vk::VkPipelineStageFlags	dstStages,
-										 vk::VkAccessFlags			dstAccesses)
+										  vk::VkAccessFlags			srcAccesses,
+										  vk::VkPipelineStageFlags	dstStages,
+										  vk::VkAccessFlags			dstAccesses)
 {
 	DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
 	DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
@@ -7727,10 +7779,18 @@
 				if ((srcStage_ & m_allowedStages) == 0)
 					continue;
 
-				if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
+				for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
 				{
-					anyWriteAvailable = true;
-					break;
+					const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+					if ((dstAccess_ & m_allowedAccesses) == 0)
+						continue;
+
+					if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != (getWriteAccessFlags() & m_allowedAccesses))
+					{
+						anyWriteAvailable = true;
+						break;
+					}
 				}
 			}
 		}
@@ -7771,7 +7831,15 @@
 				continue;
 
 			// All write operations are available after layout transition
-			m_unavailableWriteOperations[dstStage][srcStage] = 0;
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+			{
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				m_unavailableWriteOperations[dstStage][srcStage][dstAccess] = 0;
+			}
 		}
 	}
 }
@@ -7789,7 +7857,7 @@
 	// Transitivity
 	{
 		vk::VkPipelineStageFlags		oldIncompleteOperations[PIPELINESTAGE_LAST];
-		vk::VkAccessFlags				oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+		vk::VkAccessFlags				oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST][ACCESS_LAST];
 		bool							oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
 
 		deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
@@ -7824,7 +7892,15 @@
 						continue;
 
 					// Writes that are available in srcStage are also available in dstStage
-					m_unavailableWriteOperations[dstStage][sharedStage] &= oldUnavailableWriteOperations[srcStage][sharedStage];
+					for (vk::VkAccessFlags sharedAccess_ = 1; sharedAccess_ <= m_allowedAccesses; sharedAccess_ <<= 1)
+					{
+						const Access sharedAccess = accessFlagToAccess((vk::VkAccessFlagBits)sharedAccess_);
+
+						if ((sharedAccess_ & m_allowedAccesses) == 0)
+							continue;
+
+						m_unavailableWriteOperations[dstStage][sharedStage][sharedAccess] &= oldUnavailableWriteOperations[srcStage][sharedStage][sharedAccess];
+					}
 				}
 			}
 		}
@@ -7849,12 +7925,20 @@
 			if ((srcStage_ & m_allowedStages) == 0)
 				continue;
 
-			// Make srcAccesses from srcStage available in dstStage
-			if ((srcStage_ & srcStages) != 0)
-				m_unavailableWriteOperations[dstStage][srcStage] &= ~srcAccesses;
+			// Make srcAccesses from srcStage available in dstStage for dstAccess
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+			{
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
 
-			if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
-				allWritesAvailable = false;
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				if (((srcStage_ & srcStages) != 0) && ((dstAccess_ & dstAccesses) != 0))
+					m_unavailableWriteOperations[dstStage][srcStage][dstAccess] &= ~srcAccesses;
+
+				if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
+					allWritesAvailable = false;
+			}
 		}
 
 		// If all writes are available in dstStage make dstAccesses also visible
@@ -7891,9 +7975,17 @@
 			if ((srcStage_ & m_allowedStages) == 0)
 				continue;
 
-			// Some write operations are not available yet
-			if (m_unavailableWriteOperations[dstStage][srcStage] != 0)
-				return false;
+			for (vk::VkAccessFlags dstAccess_ = 1; dstAccess_ <= m_allowedAccesses; dstAccess_ <<= 1)
+			{
+				const Access dstAccess = accessFlagToAccess((vk::VkAccessFlagBits)dstAccess_);
+
+				if ((dstAccess_ & m_allowedAccesses) == 0)
+					continue;
+
+				// Some write operations are not available yet
+				if (m_unavailableWriteOperations[dstStage][srcStage][dstAccess] != 0)
+					return false;
+			}
 		}
 	}
 
@@ -8157,7 +8249,7 @@
 		{
 			ops.push_back(OP_PIPELINE_BARRIER_GLOBAL);
 
-			if (state.hasImage)
+			if (state.hasImage && (state.imageLayout != vk::VK_IMAGE_LAYOUT_UNDEFINED))
 				ops.push_back(OP_PIPELINE_BARRIER_IMAGE);
 
 			if (state.hasBuffer)