Prevent Pipeline crashing on missing non mandatory structures

When constructing a Graphics pipeline, some structures may or may
not exist, depending on what will be used by the render pass. These
structures (viewportState, multisampleState, depthStencilState and
colorBlendState) are now checked before being used, since it is
allowed for these to be null.

Bug b/118386749

Change-Id: If2759ae2554a98143b30e70624a0dc8d88c5bd43
Reviewed-on: https://swiftshader-review.googlesource.com/c/24911
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 0900a85..3205c04 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -267,15 +267,18 @@
 	context.drawType = Convert(assemblyState->topology);
 
 	const VkPipelineViewportStateCreateInfo* viewportState = pCreateInfo->pViewportState;
-	if((viewportState->flags != 0) ||
-	   (viewportState->viewportCount != 1) ||
-	   (viewportState->scissorCount	!= 1))
+	if(viewportState)
 	{
-		UNIMPLEMENTED();
-	}
+		if((viewportState->flags != 0) ||
+			(viewportState->viewportCount != 1) ||
+			(viewportState->scissorCount != 1))
+		{
+			UNIMPLEMENTED();
+		}
 
-	scissor = Convert(viewportState->pScissors[0]);
-	viewport = viewportState->pViewports[0];
+		scissor = Convert(viewportState->pScissors[0]);
+		viewport = viewportState->pViewports[0];
+	}
 
 	const VkPipelineRasterizationStateCreateInfo* rasterizationState = pCreateInfo->pRasterizationState;
 	if((rasterizationState->flags != 0) ||
@@ -291,83 +294,92 @@
 	context.slopeDepthBias = (rasterizationState->depthBiasEnable ? rasterizationState->depthBiasSlopeFactor : 0.0f);
 
 	const VkPipelineMultisampleStateCreateInfo* multisampleState = pCreateInfo->pMultisampleState;
-	if((multisampleState->flags != 0) ||
-	   (multisampleState->rasterizationSamples != VK_SAMPLE_COUNT_1_BIT) ||
-	   (multisampleState->sampleShadingEnable != 0) ||
-	   !((multisampleState->pSampleMask == nullptr) ||
-	     (*(multisampleState->pSampleMask) == 0xFFFFFFFFu)) ||
-	   (multisampleState->alphaToCoverageEnable != 0) ||
-	   (multisampleState->alphaToOneEnable != 0))
+	if(multisampleState)
 	{
-		UNIMPLEMENTED();
+		if((multisampleState->flags != 0) ||
+			(multisampleState->rasterizationSamples != VK_SAMPLE_COUNT_1_BIT) ||
+			(multisampleState->sampleShadingEnable != 0) ||
+			!((multisampleState->pSampleMask == nullptr) ||
+			(*(multisampleState->pSampleMask) == 0xFFFFFFFFu)) ||
+				(multisampleState->alphaToCoverageEnable != 0) ||
+			(multisampleState->alphaToOneEnable != 0))
+		{
+			UNIMPLEMENTED();
+		}
 	}
 
 	const VkPipelineDepthStencilStateCreateInfo* depthStencilState = pCreateInfo->pDepthStencilState;
-	if((depthStencilState->flags != 0) ||
-	   (depthStencilState->depthBoundsTestEnable != 0) ||
-	   (depthStencilState->minDepthBounds != 0.0f) ||
-	   (depthStencilState->maxDepthBounds != 1.0f))
+	if(depthStencilState)
 	{
-		UNIMPLEMENTED();
-	}
-
-	context.depthBufferEnable = depthStencilState->depthTestEnable;
-	context.depthWriteEnable = depthStencilState->depthWriteEnable;
-	context.depthCompareMode = depthStencilState->depthCompareOp;
-
-	context.stencilEnable = context.twoSidedStencil = depthStencilState->stencilTestEnable;
-	if(context.stencilEnable)
-	{
-		context.stencilMask = depthStencilState->front.compareMask;
-		context.stencilCompareMode = depthStencilState->front.compareOp;
-		context.stencilZFailOperation = depthStencilState->front.depthFailOp;
-		context.stencilFailOperation = depthStencilState->front.failOp;
-		context.stencilPassOperation = depthStencilState->front.passOp;
-		context.stencilReference = depthStencilState->front.reference;
-		context.stencilWriteMask = depthStencilState->front.writeMask;
-
-		context.stencilMaskCCW = depthStencilState->back.compareMask;
-		context.stencilCompareModeCCW = depthStencilState->back.compareOp;
-		context.stencilZFailOperationCCW = depthStencilState->back.depthFailOp;
-		context.stencilFailOperationCCW = depthStencilState->back.failOp;
-		context.stencilPassOperationCCW = depthStencilState->back.passOp;
-		context.stencilReferenceCCW = depthStencilState->back.reference;
-		context.stencilWriteMaskCCW = depthStencilState->back.writeMask;
-	}
-
-	const VkPipelineColorBlendStateCreateInfo* colorBlendState = pCreateInfo->pColorBlendState;
-	if((colorBlendState->flags != 0) ||
-	   ((colorBlendState->logicOpEnable != 0) &&
-	    (colorBlendState->attachmentCount > 1)))
-	{
-		UNIMPLEMENTED();
-	}
-
-	context.colorLogicOpEnabled = colorBlendState->logicOpEnable;
-	context.logicalOperation = colorBlendState->logicOp;
-	blendConstants.r = colorBlendState->blendConstants[0];
-	blendConstants.g = colorBlendState->blendConstants[1];
-	blendConstants.b = colorBlendState->blendConstants[2];
-	blendConstants.a = colorBlendState->blendConstants[3];
-
-	if(colorBlendState->attachmentCount == 1)
-	{
-		const VkPipelineColorBlendAttachmentState& attachment = colorBlendState->pAttachments[0];
-		if(attachment.colorWriteMask != (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT))
+		if((depthStencilState->flags != 0) ||
+		   (depthStencilState->depthBoundsTestEnable != 0) ||
+		   (depthStencilState->minDepthBounds != 0.0f) ||
+		   (depthStencilState->maxDepthBounds != 1.0f))
 		{
 			UNIMPLEMENTED();
 		}
 
-		context.alphaBlendEnable = attachment.blendEnable;
-		context.separateAlphaBlendEnable = (attachment.alphaBlendOp != attachment.colorBlendOp) ||
-		                                   (attachment.dstAlphaBlendFactor != attachment.dstColorBlendFactor) ||
-		                                   (attachment.srcAlphaBlendFactor != attachment.srcColorBlendFactor);
-		context.blendOperationStateAlpha = attachment.alphaBlendOp;
-		context.blendOperationState = attachment.colorBlendOp;
-		context.destBlendFactorStateAlpha = attachment.dstAlphaBlendFactor;
-		context.destBlendFactorState = attachment.dstColorBlendFactor;
-		context.sourceBlendFactorStateAlpha = attachment.srcAlphaBlendFactor;
-		context.sourceBlendFactorState = attachment.srcColorBlendFactor;
+		context.depthBufferEnable = depthStencilState->depthTestEnable;
+		context.depthWriteEnable = depthStencilState->depthWriteEnable;
+		context.depthCompareMode = depthStencilState->depthCompareOp;
+
+		context.stencilEnable = context.twoSidedStencil = depthStencilState->stencilTestEnable;
+		if(context.stencilEnable)
+		{
+			context.stencilMask = depthStencilState->front.compareMask;
+			context.stencilCompareMode = depthStencilState->front.compareOp;
+			context.stencilZFailOperation = depthStencilState->front.depthFailOp;
+			context.stencilFailOperation = depthStencilState->front.failOp;
+			context.stencilPassOperation = depthStencilState->front.passOp;
+			context.stencilReference = depthStencilState->front.reference;
+			context.stencilWriteMask = depthStencilState->front.writeMask;
+
+			context.stencilMaskCCW = depthStencilState->back.compareMask;
+			context.stencilCompareModeCCW = depthStencilState->back.compareOp;
+			context.stencilZFailOperationCCW = depthStencilState->back.depthFailOp;
+			context.stencilFailOperationCCW = depthStencilState->back.failOp;
+			context.stencilPassOperationCCW = depthStencilState->back.passOp;
+			context.stencilReferenceCCW = depthStencilState->back.reference;
+			context.stencilWriteMaskCCW = depthStencilState->back.writeMask;
+		}
+	}
+
+	const VkPipelineColorBlendStateCreateInfo* colorBlendState = pCreateInfo->pColorBlendState;
+	if(colorBlendState)
+	{
+		if((colorBlendState->flags != 0) ||
+		   ((colorBlendState->logicOpEnable != 0) &&
+			(colorBlendState->attachmentCount > 1)))
+		{
+			UNIMPLEMENTED();
+		}
+
+		context.colorLogicOpEnabled = colorBlendState->logicOpEnable;
+		context.logicalOperation = colorBlendState->logicOp;
+		blendConstants.r = colorBlendState->blendConstants[0];
+		blendConstants.g = colorBlendState->blendConstants[1];
+		blendConstants.b = colorBlendState->blendConstants[2];
+		blendConstants.a = colorBlendState->blendConstants[3];
+
+		if(colorBlendState->attachmentCount == 1)
+		{
+			const VkPipelineColorBlendAttachmentState& attachment = colorBlendState->pAttachments[0];
+			if(attachment.colorWriteMask != (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT))
+			{
+				UNIMPLEMENTED();
+			}
+
+			context.alphaBlendEnable = attachment.blendEnable;
+			context.separateAlphaBlendEnable = (attachment.alphaBlendOp != attachment.colorBlendOp) ||
+											   (attachment.dstAlphaBlendFactor != attachment.dstColorBlendFactor) ||
+											   (attachment.srcAlphaBlendFactor != attachment.srcColorBlendFactor);
+			context.blendOperationStateAlpha = attachment.alphaBlendOp;
+			context.blendOperationState = attachment.colorBlendOp;
+			context.destBlendFactorStateAlpha = attachment.dstAlphaBlendFactor;
+			context.destBlendFactorState = attachment.dstColorBlendFactor;
+			context.sourceBlendFactorStateAlpha = attachment.srcAlphaBlendFactor;
+			context.sourceBlendFactorState = attachment.srcColorBlendFactor;
+		}
 	}
 }