1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief VK_EXT_shader_stencil_export tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktPipelineStencilExportTests.hpp"
25 
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktPipelineUniqueRandomIterator.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkRef.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44 
45 #include "tcuTestLog.hpp"
46 #include "tcuImageCompare.hpp"
47 
48 #include "deMemory.h"
49 #include "deRandom.hpp"
50 #include "deStringUtil.hpp"
51 #include "deUniquePtr.hpp"
52 
53 #include <algorithm>
54 #include <sstream>
55 #include <vector>
56 
57 namespace vkt
58 {
59 namespace pipeline
60 {
61 
62 using namespace vk;
63 using tcu::Vec4;
64 using tcu::Vec2;
65 using tcu::UVec2;
66 using tcu::UVec4;
67 using de::UniquePtr;
68 using de::MovePtr;
69 using de::SharedPtr;
70 
71 namespace
72 {
73 
initPrograms(SourceCollections & programCollection,vk::VkFormat)74 void initPrograms (SourceCollections& programCollection, vk::VkFormat)
75 {
76 	// Vertex shader.
77 	{
78 		std::ostringstream src;
79 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
80 			<< "vec2 positions[6] = vec2[](\n"
81 			<< "	vec2(-1.0, -1.0),\n"
82 			<< "	vec2(-1.0, +1.0),\n"
83 			<< "	vec2(+1.0, -1.0),\n"
84 			<< "	vec2(+1.0, +1.0),\n"
85 			<< "	vec2(+1.0, -1.0),\n"
86 			<< "	vec2(-1.0, +1.0)\n"
87 			<< "\n"
88 			<< ");\n"
89 			<< "\n"
90 			<< "void main(void)\n"
91 			<< "{\n"
92 			<< "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
93 			<< "}\n";
94 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
95 	}
96 
97 	// Fragment shader that writes to Stencil buffer.
98 	{
99 		std::ostringstream src;
100 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
101 			<< "#extension GL_ARB_shader_stencil_export: enable\n"
102 			<< "\n"
103 			<< "void main(void)\n"
104 			<< "{\n"
105 			<< "    int refX = (int(gl_FragCoord.x) >> 4) % 2;\n"
106 			<< "    int refY = (int(gl_FragCoord.y) >> 4) % 2;\n"
107 			<< "    gl_FragStencilRefARB = (refX + refY) % 2;\n"
108 			<< "}\n";
109 		programCollection.glslSources.add("frag-stencil") << glu::FragmentSource(src.str());
110 	}
111 
112 	// Fragment shader that writes to Color buffer.
113 	{
114 		std::ostringstream src;
115 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
116 			<< "layout(location = 0) out highp vec4 fragColor;\n"
117 			<< "\n"
118 			<< "void main(void)\n"
119 			<< "{\n"
120 			<< "    fragColor = vec4(0, 0, 1, 1);\n"
121 			<< "}\n";
122 		programCollection.glslSources.add("frag-color") << glu::FragmentSource(src.str());
123 	}
124 }
125 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)126 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
127 {
128 	VkFormatProperties formatProps;
129 
130 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
131 
132 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
133 }
134 
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)135 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
136 {
137 	const VkImageCreateInfo imageParams =
138 	{
139 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
140 		DE_NULL,										// const void*				pNext;
141 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
142 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
143 		format,											// VkFormat					format;
144 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
145 		1u,												// deUint32					mipLevels;
146 		1u,												// deUint32					arrayLayers;
147 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
148 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
149 		usage,											// VkImageUsageFlags		usage;
150 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
151 		0u,												// deUint32					queueFamilyIndexCount;
152 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
153 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
154 	};
155 	return imageParams;
156 }
157 
makeTestRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat stencilFormat)158 Move<VkRenderPass> makeTestRenderPass (const DeviceInterface& vk,
159 									   const VkDevice		  device,
160 									   const VkFormat		  colorFormat,
161 									   const VkFormat		  stencilFormat)
162 {
163 	VkAttachmentDescription attachmentDescriptions[] =
164 	{
165 		{
166 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags	flags;
167 			colorFormat,											// VkFormat						format;
168 			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits		samples;
169 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp			loadOp;
170 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp			storeOp;
171 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp			stencilLoadOp;
172 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp			stencilStoreOp;
173 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout				initialLayout;
174 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout;
175 		},
176 		{
177 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags	flags;
178 			stencilFormat,											// VkFormat						format;
179 			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits		samples;
180 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp			loadOp;
181 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp			storeOp;
182 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp			stencilLoadOp;
183 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp			stencilStoreOp;
184 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout				initialLayout;
185 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// VkImageLayout				finalLayout;
186 		},
187 	};
188 
189 	VkAttachmentReference colorAttachmentReference =
190 	{
191 		0,															// deUint32			attachment;
192 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout	layout;
193 	};
194 
195 	VkAttachmentReference stencilAttachmentReference =
196 	{
197 		1,															// deUint32			attachment;
198 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,			// VkImageLayout	layout;
199 	};
200 
201 	VkSubpassDescription subpasses[] =
202 	{
203 		{
204 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
205 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
206 			0u,									// deUint32							inputAttachmentCount;
207 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
208 			0u,									// deUint32							colorAttachmentCount;
209 		    DE_NULL,							// const VkAttachmentReference*		pColorAttachments;
210 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
211 			&stencilAttachmentReference,		// const VkAttachmentReference*		pDepthStencilAttachment;
212 			0u,									// deUint32							preserveAttachmentCount;
213 			DE_NULL								// const deUint32*					pPreserveAttachments;
214 		},
215 		{
216 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
217 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
218 			0u,									// deUint32							inputAttachmentCount;
219 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
220 			1u,									// deUint32							colorAttachmentCount;
221 			&colorAttachmentReference,			// const VkAttachmentReference*		pColorAttachments;
222 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
223 			&stencilAttachmentReference,		// const VkAttachmentReference*		pDepthStencilAttachment;
224 			0u,									// deUint32							preserveAttachmentCount;
225 			DE_NULL								// const deUint32*					pPreserveAttachments;
226 		},
227 	};
228 
229 	VkSubpassDependency dependency =
230 	{
231 		0u,												// uint32_t                srcSubpass;
232 		1u,												// uint32_t                dstSubpass;
233 		VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags    srcStageMask;
234 		VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags    dstStageMask;
235 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,	// VkAccessFlags           srcAccessMask;
236 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,	// VkAccessFlags           dstAccessMask;
237 		0u,												// VkDependencyFlags       dependencyFlags;
238 	};
239 
240 	const VkRenderPassCreateInfo renderPassInfo =
241 	{
242 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
243 		DE_NULL,									// const void*						pNext;
244 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
245 		2u,											// deUint32							attachmentCount;
246 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
247 		2u,											// deUint32							subpassCount;
248 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
249 		1u,											// deUint32							dependencyCount;
250 		&dependency,								// const VkSubpassDependency*		pDependencies;
251 	};
252 
253 	return createRenderPass(vk, device, &renderPassInfo);
254 }
255 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const bool useColor)256 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
257 									   const VkDevice				device,
258 									   const VkPipelineLayout		pipelineLayout,
259 									   const VkRenderPass			renderPass,
260 									   const deUint32				subpass,
261 									   const VkShaderModule			vertexModule,
262 									   const VkShaderModule			fragmentModule,
263 									   const UVec2					renderSize,
264 									   const bool					useColor)
265 {
266 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
267 	{
268 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType                             sType;
269 		DE_NULL,														// const void*                                 pNext;
270 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags       flags;
271 		0u,																// uint32_t                                    vertexBindingDescriptionCount;
272 		DE_NULL,														// const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
273 		0u,																// uint32_t                                    vertexAttributeDescriptionCount;
274 		DE_NULL,														// const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
275 	};
276 
277 	const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
278 	{
279 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                             sType;
280 		DE_NULL,														// const void*                                 pNext;
281 		(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags     flags;
282 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							// VkPrimitiveTopology                         topology;
283 		VK_FALSE,														// VkBool32                                    primitiveRestartEnable;
284 	};
285 
286 	const VkViewport						viewport					= makeViewport(renderSize);
287 	const VkRect2D							scissor						= makeRect2D(renderSize);
288 	const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo	=
289 	{
290 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType                             sType;
291 		DE_NULL,														// const void*                                 pNext;
292 		(VkPipelineViewportStateCreateFlags)0,							// VkPipelineViewportStateCreateFlags          flags;
293 		1u,																// uint32_t                                    viewportCount;
294 		&viewport,														// const VkViewport*                           pViewports;
295 		1u,																// uint32_t                                    scissorCount;
296 		&scissor,														// const VkRect2D*                             pScissors;
297 	};
298 
299 	const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
300 	{
301 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType                          sType;
302 		DE_NULL,														// const void*                              pNext;
303 		(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStateCreateFlags  flags;
304 		VK_FALSE,														// VkBool32                                 depthClampEnable;
305 		VK_FALSE,														// VkBool32                                 rasterizerDiscardEnable;
306 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
307 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
308 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
309 		VK_FALSE,														// VkBool32									depthBiasEnable;
310 		0.0f,															// float									depthBiasConstantFactor;
311 		0.0f,															// float									depthBiasClamp;
312 		0.0f,															// float									depthBiasSlopeFactor;
313 		1.0f,															// float									lineWidth;
314 	};
315 
316 	const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
317 	{
318 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
319 		DE_NULL,														// const void*								pNext;
320 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags	flags;
321 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
322 		VK_FALSE,														// VkBool32									sampleShadingEnable;
323 		0.0f,															// float									minSampleShading;
324 		DE_NULL,														// const VkSampleMask*						pSampleMask;
325 		VK_FALSE,														// VkBool32									alphaToCoverageEnable;
326 		VK_FALSE														// VkBool32									alphaToOneEnable;
327 	};
328 
329 	const VkStencilOpState stencilOpState = makeStencilOpState(
330 		useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE,			// stencil fail
331 		useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE,			// depth & stencil pass
332 		useColor ? VK_STENCIL_OP_KEEP : VK_STENCIL_OP_REPLACE,			// depth only fail
333 		useColor ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_NEVER,			// compare op
334 		useColor ? 0xffu : 0u,											// compare mask
335 		useColor ? 0u : 0xffu,											// write mask
336 		0u);															// reference
337 
338 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
339 	{
340 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType							sType;
341 		DE_NULL,														// const void*								pNext;
342 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags	flags;
343 		VK_FALSE,														// VkBool32									depthTestEnable;
344 		VK_FALSE,														// VkBool32									depthWriteEnable;
345 		VK_COMPARE_OP_NEVER,											// VkCompareOp								depthCompareOp;
346 		VK_FALSE,														// VkBool32									depthBoundsTestEnable;
347 		VK_TRUE,														// VkBool32									stencilTestEnable;
348 		stencilOpState,													// VkStencilOpState							front;
349 		stencilOpState,													// VkStencilOpState							back;
350 		0.0f,															// float									minDepthBounds;
351 		1.0f,															// float									maxDepthBounds;
352 	};
353 
354 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
355 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
356 	{
357 		VK_FALSE,						// VkBool32					blendEnable;
358 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			srcColorBlendFactor;
359 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstColorBlendFactor;
360 		VK_BLEND_OP_ADD,				// VkBlendOp				colorBlendOp;
361 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			srcAlphaBlendFactor;
362 		VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			dstAlphaBlendFactor;
363 		VK_BLEND_OP_ADD,				// VkBlendOp				alphaBlendOp;
364 		colorComponentsAll,				// VkColorComponentFlags	colorWriteMask;
365 	};
366 
367 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
368 	{
369 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
370 		DE_NULL,														// const void*									pNext;
371 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
372 		VK_FALSE,														// VkBool32										logicOpEnable;
373 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
374 		1u,																// deUint32										attachmentCount;
375 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
376 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
377 	};
378 
379 	const VkPipelineShaderStageCreateInfo pShaderStages[] =
380 	{
381 		{
382 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
383 			DE_NULL,													// const void*							pNext;
384 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
385 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
386 			vertexModule,												// VkShaderModule						module;
387 			"main",														// const char*							pName;
388 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
389 		},
390 		{
391 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
392 			DE_NULL,													// const void*							pNext;
393 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
394 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
395 			fragmentModule,												// VkShaderModule						module;
396 			"main",														// const char*							pName;
397 			DE_NULL,													// const VkSpecializationInfo*			pSpecializationInfo;
398 		},
399 	};
400 
401 	const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
402 	{
403 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,				// VkStructureType									sType;
404 		DE_NULL,														// const void*										pNext;
405 		(VkPipelineCreateFlags)0,										// VkPipelineCreateFlags							flags;
406 	    2,																// deUint32											stageCount;
407 		pShaderStages,													// const VkPipelineShaderStageCreateInfo*			pStages;
408 		&vertexInputStateInfo,											// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
409 		&pipelineInputAssemblyStateInfo,								// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
410 		DE_NULL,														// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
411 		&pipelineViewportStateInfo,										// const VkPipelineViewportStateCreateInfo*			pViewportState;
412 		&pipelineRasterizationStateInfo,								// const VkPipelineRasterizationStateCreateInfo*	pRasterizationState;
413 		&pipelineMultisampleStateInfo,									// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
414 		&pipelineDepthStencilStateInfo,									// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
415 		&pipelineColorBlendStateInfo,									// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
416 		DE_NULL,														// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
417 		pipelineLayout,													// VkPipelineLayout									layout;
418 		renderPass,														// VkRenderPass										renderPass;
419 		subpass,														// deUint32											subpass;
420 		DE_NULL,														// VkPipeline										basePipelineHandle;
421 		0,																// deInt32											basePipelineIndex;
422 	};
423 
424 	return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
425 }
426 
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const deUint32 patternSize,const Vec4 & clearColor,const Vec4 & color)427 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat	format,
428 										  const UVec2&				renderSize,
429 										  const deUint32			patternSize,
430 										  const Vec4&				clearColor,
431 										  const Vec4&				color)
432 {
433 	tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
434 	tcu::clear(image.getAccess(), clearColor);
435 
436 	deUint32 rows = renderSize.y() / patternSize;
437 	deUint32 cols = renderSize.x() / patternSize;
438 
439 	for (deUint32 i = 0; i < rows; i++)
440 	{
441 		for (deUint32 j = 0; j < cols; j++)
442 		{
443 			if ((i + j) % 2 == 0)
444 				tcu::clear(tcu::getSubregion(image.getAccess(), i * patternSize, j * patternSize, patternSize, patternSize), color);
445 		}
446 	}
447 
448 	return image;
449 }
450 
testStencilExportReplace(Context & context,vk::VkFormat stencilFormat)451 tcu::TestStatus testStencilExportReplace (Context& context, vk::VkFormat stencilFormat)
452 {
453 	auto& log = context.getTestContext().getLog();
454 	log << tcu::TestLog::Message << "Drawing to stencil using shader then using it for another draw." << tcu::TestLog::EndMessage;
455 
456 	const DeviceInterface&			vk					= context.getDeviceInterface();
457 	const VkDevice					device				= context.getDevice();
458 	Allocator&						allocator			= context.getDefaultAllocator();
459 
460 	const UVec2						renderSize			(128, 128);
461 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
462 	const Vec4						clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
463 	const VkDeviceSize				colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
464 
465 	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
466 	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
467 
468 	// Zero color buffer.
469 	deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
470 	flushAlloc(vk, device, *colorBufferAlloc);
471 
472 	// Draw two subpasses: first write the stencil data, then use that data when writing color.
473 	//
474 	// The first pass will produce a checkerboard stencil by having the shader filling gl_FragStencilRefARB with 0 or 1,
475 	// and using OP_REPLACE to write those values to the stencil buffer.
476 	//
477 	// The second pass will use the stencil with a compare operation EQUAL with reference value 0.
478 	{
479 		const VkImageSubresourceRange	stencilSubresourceRange	= makeImageSubresourceRange	(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
480 		Move<VkImage>					stencilImage			= makeImage					(vk, device, makeImageCreateInfo(stencilFormat, renderSize, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
481 		MovePtr<Allocation>				stencilImageAlloc		= bindImage					(vk, device, allocator, *stencilImage, MemoryRequirement::Any);
482 		Move<VkImageView>				stencilAttachment		= makeImageView				(vk, device, *stencilImage, VK_IMAGE_VIEW_TYPE_2D, stencilFormat, stencilSubresourceRange);
483 
484 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
485 		Move<VkImage>					colorImage				= makeImage					(vk, device, makeImageCreateInfo(colorFormat, renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
486 		MovePtr<Allocation>				colorImageAlloc			= bindImage					(vk, device, allocator, *colorImage, MemoryRequirement::Any);
487 		Move<VkImageView>				colorAttachment			= makeImageView				(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
488 
489 		Move<VkShaderModule>			vertexModule			= createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0);
490 		Move<VkShaderModule>			fragmentStencilModule	= createShaderModule		(vk, device, context.getBinaryCollection().get("frag-stencil"), 0);
491 		Move<VkShaderModule>			fragmentColorModule		= createShaderModule		(vk, device, context.getBinaryCollection().get("frag-color"), 0);
492 
493 		Move<VkRenderPass>				renderPass				= makeTestRenderPass		(vk, device, colorFormat, stencilFormat);
494 		Move<VkPipelineLayout>			pipelineLayout			= makePipelineLayout		(vk, device);
495 		Move<VkPipeline>				stencilPipeline			= makeGraphicsPipeline		(vk, device, *pipelineLayout, *renderPass, 0, *vertexModule, *fragmentStencilModule, renderSize, false);
496 		Move<VkPipeline>				colorPipeline			= makeGraphicsPipeline		(vk, device, *pipelineLayout, *renderPass, 1, *vertexModule, *fragmentColorModule, renderSize, true);
497 
498 		const VkImageView attachments[] =
499 		{
500 			*colorAttachment,
501 			*stencilAttachment,
502 		};
503 		Move<VkFramebuffer>				framebuffer				= makeFramebuffer			(vk, device, *renderPass, 2u, &attachments[0], renderSize.x(), renderSize.y());
504 
505 		Move<VkCommandPool>				cmdPool					= createCommandPool			(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex());
506 		Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer		(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
507 
508 		const VkQueue					queue					= context.getUniversalQueue();
509 
510 		beginCommandBuffer(vk, *cmdBuffer);
511 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 0u);
512 
513 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *stencilPipeline);
514 		vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
515 
516 		vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
517 
518 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *colorPipeline);
519 		vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
520 
521 		endRenderPass(vk, *cmdBuffer);
522 
523 		copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(renderSize.x(), renderSize.y()));
524 
525 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
526 		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
527 	}
528 
529 	// Compare the resulting color buffer.
530 	{
531 		invalidateAlloc(vk, device, *colorBufferAlloc);
532 		const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
533 
534 		tcu::TextureLevel					referenceImage	= generateReferenceImage(mapVkFormat(colorFormat), renderSize, 1 << 4, clearColor, Vec4(0, 0, 1, 1));
535 
536 		if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
537 			TCU_FAIL("Rendered image is not correct");
538 	}
539 
540 	return tcu::TestStatus::pass("OK");
541 }
542 
checkSupport(Context & context,vk::VkFormat stencilFormat)543 void checkSupport (Context& context, vk::VkFormat stencilFormat)
544 {
545 	context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
546 
547 	if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), stencilFormat))
548 		TCU_THROW(NotSupportedError, "Image format not supported");
549 }
550 
551 } // anonymous
552 
createStencilExportTests(tcu::TestContext & testCtx)553 tcu::TestCaseGroup* createStencilExportTests (tcu::TestContext& testCtx)
554 {
555 	struct
556 	{
557 		const vk::VkFormat	format;
558 		const std::string	name;
559 	} kFormats[] =
560 	{
561 		{ vk::VK_FORMAT_S8_UINT,			"s8_uint"				},
562 		{ vk::VK_FORMAT_D24_UNORM_S8_UINT,	"d24_unorm_s8_uint"		},
563 		{ vk::VK_FORMAT_D32_SFLOAT_S8_UINT,	"d32_sfloat_s8_uint"	},
564 	};
565 
566 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_stencil_export", ""));
567 	for (int fmtIdx = 0; fmtIdx < DE_LENGTH_OF_ARRAY(kFormats); ++fmtIdx)
568 	{
569 		de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, kFormats[fmtIdx].name.c_str(), ""));
570 		addFunctionCaseWithPrograms<vk::VkFormat>(formatGroup.get(), "op_replace", "", checkSupport, initPrograms, testStencilExportReplace, kFormats[fmtIdx].format);
571 		group->addChild(formatGroup.release());
572 	}
573 	return group.release();
574 }
575 
576 } // pipeline
577 } // vkt
578