Zero-initialize the context state and data

Using an initialization method or in-class initialization of each member
is bug-prone. Zero-initialization performed by the default constructor
guarantees repeatability.

Also don't skip drawing when the multisample mask is zero. Pipeline
stages prior to fragment processing may have side-effects.

Bug: b/155359026
Change-Id: Ibab131a41282fbdc4f5f84208776725eb3c786bd
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/45748
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index da0e2c4..b5f36bf 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -24,11 +24,6 @@
 
 namespace sw {
 
-Context::Context()
-{
-	init();
-}
-
 bool Context::isDrawPoint(bool polygonModeAware) const
 {
 	switch(topology)
@@ -85,55 +80,6 @@
 	return false;
 }
 
-void Context::init()
-{
-	for(int i = 0; i < RENDERTARGETS; ++i)
-	{
-		renderTarget[i] = nullptr;
-	}
-
-	depthBuffer = nullptr;
-	stencilBuffer = nullptr;
-
-	stencilEnable = false;
-	frontStencil = {};
-	backStencil = {};
-
-	robustBufferAccess = false;
-
-	rasterizerDiscard = false;
-
-	depthCompareMode = VK_COMPARE_OP_LESS;
-	depthBoundsTestEnable = false;
-	depthBufferEnable = false;
-	depthWriteEnable = false;
-
-	cullMode = VK_CULL_MODE_FRONT_BIT;
-	frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
-	provokingVertexMode = VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
-	lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
-
-	depthBias = 0.0f;
-	slopeDepthBias = 0.0f;
-
-	for(int i = 0; i < RENDERTARGETS; i++)
-	{
-		colorWriteMask[i] = 0x0000000F;
-	}
-
-	pipelineLayout = nullptr;
-
-	pixelShader = nullptr;
-	vertexShader = nullptr;
-
-	occlusionEnabled = false;
-
-	lineWidth = 1.0f;
-
-	sampleMask = 0xFFFFFFFF;
-	alphaToCoverage = false;
-}
-
 bool Context::depthWriteActive() const
 {
 	if(!depthBufferActive()) return false;
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index cee48ad..a54ec2d 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -73,9 +73,7 @@
 class Context
 {
 public:
-	Context();
-
-	void init();
+	Context() = default;
 
 	bool isDrawPoint(bool polygonModeAware) const;
 	bool isDrawLine(bool polygonModeAware) const;
diff --git a/src/Device/Renderer.cpp b/src/Device/Renderer.cpp
index 5908de8..22f10f8 100644
--- a/src/Device/Renderer.cpp
+++ b/src/Device/Renderer.cpp
@@ -187,13 +187,6 @@
 	auto id = nextDrawID++;
 	MARL_SCOPED_EVENT("draw %d", id);
 
-	int ms = context->sampleCount;
-
-	if(!context->multiSampleMask)
-	{
-		return;
-	}
-
 	marl::Pool<sw::DrawCall>::Loan draw;
 	{
 		MARL_SCOPED_EVENT("drawCallPool.borrow()");
@@ -214,6 +207,7 @@
 	}
 
 	DrawCall::SetupFunction setupPrimitives = nullptr;
+	int ms = context->sampleCount;
 	unsigned int numPrimitivesPerBatch = MaxBatchSize / ms;
 
 	if(context->isDrawTriangle(false))
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index e0af236..ffcb353 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -291,6 +291,7 @@
 	context.polygonMode = rasterizationState->polygonMode;
 	context.depthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasConstantFactor : 0.0f;
 	context.slopeDepthBias = (rasterizationState->depthBiasEnable != VK_FALSE) ? rasterizationState->depthBiasSlopeFactor : 0.0f;
+	context.lineWidth = rasterizationState->lineWidth;
 
 	const VkBaseInStructure *extensionCreateInfo = reinterpret_cast<const VkBaseInStructure *>(rasterizationState->pNext);
 	while(extensionCreateInfo)
@@ -321,6 +322,10 @@
 		extensionCreateInfo = extensionCreateInfo->pNext;
 	}
 
+	// The sample count affects the batch size, so it needs initialization even if rasterization is disabled.
+	// TODO(b/147812380): Eliminate the dependency between multisampling and batch size.
+	context.sampleCount = 1;
+
 	const VkPipelineMultisampleStateCreateInfo *multisampleState = pCreateInfo->pMultisampleState;
 	if(multisampleState)
 	{
@@ -356,6 +361,10 @@
 		{
 			context.sampleMask = multisampleState->pSampleMask[0];
 		}
+		else  // "If pSampleMask is NULL, it is treated as if the mask has all bits set to 1."
+		{
+			context.sampleMask = ~0;
+		}
 
 		context.alphaToCoverage = (multisampleState->alphaToCoverageEnable != VK_FALSE);
 	}