• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "vktPipelineMakeUtil.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktPipelineUniqueRandomIterator.hpp"
31 #include "vktTestCase.hpp"
32 #include "vktTestCaseUtil.hpp"
33 
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 
44 #include "tcuTestLog.hpp"
45 #include "tcuImageCompare.hpp"
46 
47 #include "deMemory.h"
48 #include "deRandom.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
51 
52 #include <algorithm>
53 #include <sstream>
54 #include <vector>
55 
56 namespace vkt
57 {
58 namespace pipeline
59 {
60 
61 using namespace vk;
62 using tcu::Vec4;
63 using tcu::Vec2;
64 using tcu::UVec2;
65 using tcu::UVec4;
66 using de::UniquePtr;
67 using de::MovePtr;
68 using de::SharedPtr;
69 
70 namespace
71 {
72 
73 struct TestParams
74 {
75 	PipelineConstructionType	pipelineConstructionType;
76 	vk::VkFormat				stencilFormat;
77 	bool						early_and_late;
78 };
79 
80 static const std::string ExecutionModeStencil[] =
81 {
82 	"StencilRefGreaterFrontAMD",
83 	"StencilRefLessFrontAMD",
84 	"StencilRefGreaterBackAMD",
85 	"StencilRefLessBackAMD",
86 	"StencilRefUnchangedFrontAMD",
87 	"StencilRefUnchangedBackAMD",
88 };
89 
90 enum ExecutionModeEarlyAndLate
91 {
92 	MODE_STENCIL_REF_GREATER_FRONT_AMD = 0,
93 	MODE_STENCIL_REF_LESS_FRONT_AMD,
94 	MODE_STENCIL_REF_GREATER_BACK_AMD,
95 	MODE_STENCIL_REF_LESS_BACK_AMD,
96 	MODE_STENCIL_REF_UNCHANGED_FRONT_AMD,
97 	MODE_STENCIL_REF_UNCHANGED_BACK_AMD,
98 	MODE_COUNT_AMD
99 };
100 
initPrograms(SourceCollections & programCollection,TestParams paramaeters)101 void initPrograms (SourceCollections& programCollection, TestParams paramaeters)
102 {
103 	// Vertex shader.
104 	{
105 		std::ostringstream src;
106 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
107 			<< "vec2 positions[6] = vec2[](\n"
108 			<< "	vec2(-1.0, -1.0),\n"
109 			<< "	vec2(-1.0, +1.0),\n"
110 			<< "	vec2(+1.0, -1.0),\n"
111 			<< "	vec2(+1.0, +1.0),\n"
112 			<< "	vec2(+1.0, -1.0),\n"
113 			<< "	vec2(-1.0, +1.0)\n"
114 			<< "\n"
115 			<< ");\n"
116 			<< "\n"
117 			<< "void main(void)\n"
118 			<< "{\n"
119 			<< "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
120 			<< "}\n";
121 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
122 	}
123 
124 	// Fragment shader that writes to Stencil buffer.
125 	if (paramaeters.early_and_late)
126 	{
127 		for (int stencilModeNdx = 0; stencilModeNdx < 6; stencilModeNdx++)
128 		{
129 			const std::string src =
130 			"; SPIR-V\n"
131 			"; Version: 1.0\n"
132 			"; Bound: 36\n"
133 			"; Schema: 0\n"
134 			"OpCapability Shader\n"
135 			"OpCapability StencilExportEXT\n"
136 			"OpExtension \"SPV_EXT_shader_stencil_export\"\n"
137 			"OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
138 			"%1 = OpExtInstImport \"GLSL.std.450\"\n"
139 			"OpMemoryModel Logical GLSL450\n"
140 			"OpEntryPoint Fragment %4 \"main\" %12 %31\n"
141 			"OpExecutionMode %4 StencilRefReplacingEXT\n"
142 			"OpExecutionMode %4 OriginUpperLeft\n"
143 			"OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
144 			"OpExecutionMode %4 " + ExecutionModeStencil[stencilModeNdx] + "\n"
145 			"OpDecorate %12 BuiltIn FragCoord\n"
146 			"OpDecorate %31 BuiltIn FragStencilRefEXT\n"
147 			"%2 = OpTypeVoid\n"
148 			"%3 = OpTypeFunction %2\n"
149 			"%6 = OpTypeInt 32 1\n"
150 			"%7 = OpTypePointer Function %6\n"
151 			"%9 = OpTypeFloat 32\n"
152 			"%10 = OpTypeVector %9 4\n"
153 			"%11 = OpTypePointer Input %10\n"
154 			"%12 = OpVariable %11 Input\n"
155 			"%13 = OpTypeInt 32 0\n"
156 			"%14 = OpConstant %13 0\n"
157 			"%15 = OpTypePointer Input %9\n"
158 			"%19 = OpConstant %6 4\n"
159 			"%21 = OpConstant %6 2\n"
160 			"%24 = OpConstant %13 1\n"
161 			"%30 = OpTypePointer Output %6\n"
162 			"%31 = OpVariable %30 Output\n"
163 			"%4 = OpFunction %2 None %3\n"
164 			"%5 = OpLabel\n"
165 			"%8 = OpVariable %7 Function\n"
166 			"%23 = OpVariable %7 Function\n"
167 			"%16 = OpAccessChain %15 %12 %14\n"
168 			"%17 = OpLoad %9 %16\n"
169 			"%18 = OpConvertFToS %6 %17\n"
170 			"%20 = OpShiftRightArithmetic %6 %18 %19\n"
171 			"%22 = OpSMod %6 %20 %21\n"
172 			"OpStore %8 %22\n"
173 			"%25 = OpAccessChain %15 %12 %24\n"
174 			"%26 = OpLoad %9 %25\n"
175 			"%27 = OpConvertFToS %6 %26\n"
176 			"%28 = OpShiftRightArithmetic %6 %27 %19\n"
177 			"%29 = OpSMod %6 %28 %21\n"
178 			"OpStore %23 %29\n"
179 			"%32 = OpLoad %6 %8\n"
180 			"%33 = OpLoad %6 %23\n"
181 			"%34 = OpIAdd %6 %32 %33\n"
182 			"%35 = OpSMod %6 %34 %21\n"
183 			"OpStore %31 %35\n"
184 			"OpReturn\n"
185 			"OpFunctionEnd\n";
186 
187 			std::ostringstream shaderName;
188 			shaderName << "frag-stencil" << stencilModeNdx;
189 			programCollection.spirvAsmSources.add(shaderName.str()) << src << SpirVAsmBuildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_1);
190 		}
191 	}
192 	else
193 	{
194 		std::ostringstream src;
195 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
196 			<< "#extension GL_ARB_shader_stencil_export: enable\n"
197 			<< "\n"
198 			<< "void main(void)\n"
199 			<< "{\n"
200 			<< "    int refX = (int(gl_FragCoord.x) >> 4) % 2;\n"
201 			<< "    int refY = (int(gl_FragCoord.y) >> 4) % 2;\n"
202 			<< "    gl_FragStencilRefARB = (refX + refY) % 2;\n"
203 			<< "}\n";
204 		programCollection.glslSources.add("frag-stencil0") << glu::FragmentSource(src.str());
205 	}
206 
207 	// Fragment shader that writes to Color buffer.
208 	{
209 		std::ostringstream src;
210 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
211 			<< "layout(location = 0) out highp vec4 fragColor;\n"
212 			<< "\n"
213 			<< "void main(void)\n"
214 			<< "{\n"
215 			<< "    fragColor = vec4(0, 0, 1, 1);\n"
216 			<< "}\n";
217 		programCollection.glslSources.add("frag-color") << glu::FragmentSource(src.str());
218 	}
219 }
220 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)221 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, VkPhysicalDevice device, VkFormat format)
222 {
223 	VkFormatProperties formatProps;
224 
225 	instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
226 
227 	return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
228 }
229 
makeImageCreateInfo(const VkFormat format,const UVec2 & size,VkImageUsageFlags usage)230 VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const UVec2& size, VkImageUsageFlags usage)
231 {
232 	const VkImageCreateInfo imageParams =
233 	{
234 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
235 		DE_NULL,										// const void*				pNext;
236 		(VkImageCreateFlags)0,							// VkImageCreateFlags		flags;
237 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType;
238 		format,											// VkFormat					format;
239 		makeExtent3D(size.x(), size.y(), 1),			// VkExtent3D				extent;
240 		1u,												// deUint32					mipLevels;
241 		1u,												// deUint32					arrayLayers;
242 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
243 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
244 		usage,											// VkImageUsageFlags		usage;
245 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
246 		0u,												// deUint32					queueFamilyIndexCount;
247 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
248 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
249 	};
250 	return imageParams;
251 }
252 
makeTestRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat stencilFormat)253 Move<VkRenderPass> makeTestRenderPass (const DeviceInterface& vk,
254 									   const VkDevice		  device,
255 									   const VkFormat		  colorFormat,
256 									   const VkFormat		  stencilFormat)
257 {
258 	VkAttachmentDescription attachmentDescriptions[] =
259 	{
260 		{
261 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags	flags;
262 			colorFormat,											// VkFormat						format;
263 			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits		samples;
264 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp			loadOp;
265 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp			storeOp;
266 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp			stencilLoadOp;
267 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp			stencilStoreOp;
268 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout				initialLayout;
269 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// VkImageLayout				finalLayout;
270 		},
271 		{
272 			(VkAttachmentDescriptionFlags)0,						// VkAttachmentDescriptionFlags	flags;
273 			stencilFormat,											// VkFormat						format;
274 			VK_SAMPLE_COUNT_1_BIT,									// VkSampleCountFlagBits		samples;
275 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// VkAttachmentLoadOp			loadOp;
276 			VK_ATTACHMENT_STORE_OP_DONT_CARE,						// VkAttachmentStoreOp			storeOp;
277 			VK_ATTACHMENT_LOAD_OP_CLEAR,							// VkAttachmentLoadOp			stencilLoadOp;
278 			VK_ATTACHMENT_STORE_OP_STORE,							// VkAttachmentStoreOp			stencilStoreOp;
279 			VK_IMAGE_LAYOUT_UNDEFINED,								// VkImageLayout				initialLayout;
280 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// VkImageLayout				finalLayout;
281 		},
282 	};
283 
284 	VkAttachmentReference colorAttachmentReference =
285 	{
286 		0,															// deUint32			attachment;
287 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,					// VkImageLayout	layout;
288 	};
289 
290 	VkAttachmentReference stencilAttachmentReference =
291 	{
292 		1,															// deUint32			attachment;
293 		VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,			// VkImageLayout	layout;
294 	};
295 
296 	VkSubpassDescription subpasses[] =
297 	{
298 		{
299 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
300 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
301 			0u,									// deUint32							inputAttachmentCount;
302 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
303 			0u,									// deUint32							colorAttachmentCount;
304 		    DE_NULL,							// const VkAttachmentReference*		pColorAttachments;
305 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
306 			&stencilAttachmentReference,		// const VkAttachmentReference*		pDepthStencilAttachment;
307 			0u,									// deUint32							preserveAttachmentCount;
308 			DE_NULL								// const deUint32*					pPreserveAttachments;
309 		},
310 		{
311 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
312 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
313 			0u,									// deUint32							inputAttachmentCount;
314 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
315 			1u,									// deUint32							colorAttachmentCount;
316 			&colorAttachmentReference,			// const VkAttachmentReference*		pColorAttachments;
317 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
318 			&stencilAttachmentReference,		// const VkAttachmentReference*		pDepthStencilAttachment;
319 			0u,									// deUint32							preserveAttachmentCount;
320 			DE_NULL								// const deUint32*					pPreserveAttachments;
321 		},
322 	};
323 
324 	VkSubpassDependency dependency =
325 	{
326 		0u,												// uint32_t                srcSubpass;
327 		1u,												// uint32_t                dstSubpass;
328 		VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags    srcStageMask;
329 		VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,		// VkPipelineStageFlags    dstStageMask;
330 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,	// VkAccessFlags           srcAccessMask;
331 		VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,	// VkAccessFlags           dstAccessMask;
332 		0u,												// VkDependencyFlags       dependencyFlags;
333 	};
334 
335 	const VkRenderPassCreateInfo renderPassInfo =
336 	{
337 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
338 		DE_NULL,									// const void*						pNext;
339 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
340 		2u,											// deUint32							attachmentCount;
341 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
342 		2u,											// deUint32							subpassCount;
343 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
344 		1u,											// deUint32							dependencyCount;
345 		&dependency,								// const VkSubpassDependency*		pDependencies;
346 	};
347 
348 	return createRenderPass(vk, device, &renderPassInfo);
349 }
350 
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const deUint32 subpass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const UVec2 renderSize,const bool useColor,const bool earlyLate=false)351 void preparePipelineWrapper(GraphicsPipelineWrapper&	gpw,
352 							const VkPipelineLayout		pipelineLayout,
353 							const VkRenderPass			renderPass,
354 							const deUint32				subpass,
355 							const VkShaderModule		vertexModule,
356 							const VkShaderModule		fragmentModule,
357 							const UVec2					renderSize,
358 							const bool					useColor,
359 							const bool					earlyLate = false)
360 {
361 	const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
362 	{
363 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
364 		DE_NULL,														// const void*									pNext;
365 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags;
366 		0u,																// uint32_t										vertexBindingDescriptionCount;
367 		DE_NULL,														// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
368 		0u,																// uint32_t										vertexAttributeDescriptionCount;
369 		DE_NULL,														// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
370 	};
371 
372 	const std::vector<VkViewport>	viewport	{ makeViewport(renderSize) };
373 	const std::vector<VkRect2D>		scissor		{ makeRect2D(renderSize) };
374 
375 	const VkStencilOpState stencilOpState = makeStencilOpState(
376 		useColor ? VK_STENCIL_OP_KEEP  : VK_STENCIL_OP_REPLACE,										// stencil fail
377 		useColor ? VK_STENCIL_OP_KEEP  : (earlyLate ? VK_STENCIL_OP_KEEP  : VK_STENCIL_OP_REPLACE),	// depth & stencil pass
378 		useColor ? VK_STENCIL_OP_KEEP  : (earlyLate ? VK_STENCIL_OP_KEEP  : VK_STENCIL_OP_REPLACE),	// depth only fail
379 		useColor ? VK_COMPARE_OP_EQUAL : (earlyLate ? VK_COMPARE_OP_EQUAL : VK_COMPARE_OP_NEVER),	// compare op VK_COMPARE_OP_ALWAYS
380 		useColor ? 0xffu : 0xffu,																	// compare mask
381 		useColor ? 0u : 0xffu,																		// write mask
382 		useColor ? 0u : 1u);																		// reference
383 
384 	VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo
385 	{
386 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType;
387 		DE_NULL,														// const void*									pNext;
388 		(VkPipelineDepthStencilStateCreateFlags)0,						// VkPipelineDepthStencilStateCreateFlags		flags;
389 		VK_FALSE,														// VkBool32										depthTestEnable;
390 		VK_FALSE,														// VkBool32										depthWriteEnable;
391 		VK_COMPARE_OP_NEVER,											// VkCompareOp									depthCompareOp;
392 		VK_FALSE,														// VkBool32										depthBoundsTestEnable;
393 		VK_TRUE,														// VkBool32										stencilTestEnable;
394 		stencilOpState,													// VkStencilOpState								front;
395 		stencilOpState,													// VkStencilOpState								back;
396 		0.0f,															// float										minDepthBounds;
397 		1.0f,															// float										maxDepthBounds;
398 	};
399 
400 	const VkColorComponentFlags					colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
401 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState
402 	{
403 		VK_FALSE,														// VkBool32										blendEnable;
404 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcColorBlendFactor;
405 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstColorBlendFactor;
406 		VK_BLEND_OP_ADD,												// VkBlendOp									colorBlendOp;
407 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								srcAlphaBlendFactor;
408 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor								dstAlphaBlendFactor;
409 		VK_BLEND_OP_ADD,												// VkBlendOp									alphaBlendOp;
410 		colorComponentsAll,												// VkColorComponentFlags						colorWriteMask;
411 	};
412 
413 	const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo
414 	{
415 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
416 		DE_NULL,														// const void*									pNext;
417 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
418 		VK_FALSE,														// VkBool32										logicOpEnable;
419 		VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
420 		1u,																// deUint32										attachmentCount;
421 		&pipelineColorBlendAttachmentState,								// const VkPipelineColorBlendAttachmentState*	pAttachments;
422 		{ 0.0f, 0.0f, 0.0f, 0.0f },										// float										blendConstants[4];
423 	};
424 
425 	gpw.setDefaultRasterizationState()
426 	   .setDefaultMultisampleState()
427 	   .setupVertexInputState(&vertexInputStateInfo)
428 	   .setupPreRasterizationShaderState(viewport,
429 										 scissor,
430 										 pipelineLayout,
431 										 renderPass,
432 										 subpass,
433 										 vertexModule)
434 	   .setupFragmentShaderState(pipelineLayout, renderPass, subpass, fragmentModule, &pipelineDepthStencilStateInfo)
435 	   .setupFragmentOutputState(renderPass, subpass, &pipelineColorBlendStateInfo)
436 	   .setMonolithicPipelineLayout(pipelineLayout)
437 	   .buildPipeline();
438 }
439 
generateReferenceImage(const tcu::TextureFormat format,const UVec2 & renderSize,const deUint32 patternSize,const Vec4 & clearColor,const Vec4 & color)440 tcu::TextureLevel generateReferenceImage (const tcu::TextureFormat	format,
441 										  const UVec2&				renderSize,
442 										  const deUint32			patternSize,
443 										  const Vec4&				clearColor,
444 										  const Vec4&				color)
445 {
446 	tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
447 	tcu::clear(image.getAccess(), clearColor);
448 
449 	deUint32 rows = renderSize.y() / patternSize;
450 	deUint32 cols = renderSize.x() / patternSize;
451 
452 	for (deUint32 i = 0; i < rows; i++)
453 	{
454 		for (deUint32 j = 0; j < cols; j++)
455 		{
456 			if ((i + j) % 2 == 0)
457 				tcu::clear(tcu::getSubregion(image.getAccess(), i * patternSize, j * patternSize, patternSize, patternSize), color);
458 		}
459 	}
460 
461 	return image;
462 }
463 
testStencilExportReplace(Context & context,TestParams params)464 tcu::TestStatus testStencilExportReplace (Context& context, TestParams params)
465 {
466 	auto& log = context.getTestContext().getLog();
467 	log << tcu::TestLog::Message << "Drawing to stencil using shader then using it for another draw." << tcu::TestLog::EndMessage;
468 
469 	const DeviceInterface&			vk					= context.getDeviceInterface();
470 	const VkDevice					device				= context.getDevice();
471 	Allocator&						allocator			= context.getDefaultAllocator();
472 
473 	const UVec2						renderSize			(128, 128);
474 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
475 	const Vec4						clearColor			(0.5f, 0.5f, 0.5f, 1.0f);
476 	const VkDeviceSize				colorBufferSize		= renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
477 
478 	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
479 	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
480 
481 	// Zero color buffer.
482 	deMemset(colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(colorBufferSize));
483 	flushAlloc(vk, device, *colorBufferAlloc);
484 
485 	// Draw two subpasses: first write the stencil data, then use that data when writing color.
486 	//
487 	// The first pass will produce a checkerboard stencil by having the shader filling gl_FragStencilRefARB with 0 or 1,
488 	// and using OP_REPLACE to write those values to the stencil buffer.
489 	//
490 	// The second pass will use the stencil with a compare operation EQUAL with reference value 0.
491 	{
492 		const VkImageSubresourceRange	stencilSubresourceRange	= makeImageSubresourceRange	(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
493 		Move<VkImage>					stencilImage			= makeImage					(vk, device, makeImageCreateInfo(params.stencilFormat, renderSize, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
494 		MovePtr<Allocation>				stencilImageAlloc		= bindImage					(vk, device, allocator, *stencilImage, MemoryRequirement::Any);
495 		Move<VkImageView>				stencilAttachment		= makeImageView				(vk, device, *stencilImage, VK_IMAGE_VIEW_TYPE_2D, params.stencilFormat, stencilSubresourceRange);
496 
497 		const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
498 		Move<VkImage>					colorImage				= makeImage					(vk, device, makeImageCreateInfo(colorFormat, renderSize, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
499 		MovePtr<Allocation>				colorImageAlloc			= bindImage					(vk, device, allocator, *colorImage, MemoryRequirement::Any);
500 		Move<VkImageView>				colorAttachment			= makeImageView				(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
501 
502 		Move<VkShaderModule>			vertexModule			= createShaderModule		(vk, device, context.getBinaryCollection().get("vert"), 0);
503 		Move<VkShaderModule>			fragmentColorModule		= createShaderModule		(vk, device, context.getBinaryCollection().get("frag-color"), 0);
504 
505 		Move<VkRenderPass>				renderPass				= makeTestRenderPass		(vk, device, colorFormat, params.stencilFormat);
506 		Move<VkPipelineLayout>			pipelineLayout			= makePipelineLayout		(vk, device);
507 		GraphicsPipelineWrapper			colorPipeline										(vk, device, params.pipelineConstructionType);
508 
509 		preparePipelineWrapper(colorPipeline, *pipelineLayout, *renderPass, 1, *vertexModule, *fragmentColorModule, renderSize, true);
510 
511 		const VkImageView attachments[] =
512 		{
513 			*colorAttachment,
514 			*stencilAttachment,
515 		};
516 		Move<VkFramebuffer>				framebuffer				= makeFramebuffer			(vk, device, *renderPass, 2u, &attachments[0], renderSize.x(), renderSize.y());
517 
518 		Move<VkCommandPool>				cmdPool					= createCommandPool			(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex());
519 		Move<VkCommandBuffer>			cmdBuffer				= allocateCommandBuffer		(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
520 		const VkQueue					queue					= context.getUniversalQueue	();
521 		tcu::TextureLevel				referenceImage			= generateReferenceImage	(mapVkFormat(colorFormat), renderSize, 1 << 4, clearColor, Vec4(0, 0, 1, 1));
522 
523 		const int stencilModeCount = (params.early_and_late ? MODE_COUNT_AMD : 1);
524 
525 		for (int stencilModeNdx = 0; stencilModeNdx < stencilModeCount; stencilModeNdx++)
526 		{
527 			std::ostringstream shaderName;
528 			shaderName << "frag-stencil" << stencilModeNdx;
529 
530 			Move<VkShaderModule>			fragmentStencilModule	= createShaderModule(vk, device, context.getBinaryCollection().get(shaderName.str()), 0);
531 			GraphicsPipelineWrapper			stencilPipeline			(vk, device, params.pipelineConstructionType);
532 
533 			preparePipelineWrapper(stencilPipeline, *pipelineLayout, *renderPass, 0, *vertexModule, *fragmentStencilModule, renderSize, false);
534 			beginCommandBuffer(vk, *cmdBuffer);
535 			if (params.early_and_late)
536 			{
537 				switch (stencilModeNdx)
538 				{
539 				case MODE_STENCIL_REF_GREATER_FRONT_AMD:
540 				case MODE_STENCIL_REF_GREATER_BACK_AMD:
541 					beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);//0
542 					break;
543 				case MODE_STENCIL_REF_LESS_FRONT_AMD:
544 				case MODE_STENCIL_REF_LESS_BACK_AMD:
545 					beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);//10
546 					break;
547 				default:
548 					beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 1u);
549 					break;
550 				}
551 			}
552 			else
553 			{
554 				beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), clearColor, 0.0, 0u);
555 			}
556 
557 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, stencilPipeline.getPipeline());
558 			vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
559 
560 			vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
561 
562 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, colorPipeline.getPipeline());
563 			vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
564 
565 			endRenderPass(vk, *cmdBuffer);
566 
567 			copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(renderSize.x(), renderSize.y()));
568 
569 			VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
570 			submitCommandsAndWait(vk, device, queue, *cmdBuffer);
571 
572 			// Compare the resulting color buffer.
573 			{
574 				invalidateAlloc(vk, device, *colorBufferAlloc);
575 				const tcu::ConstPixelBufferAccess	resultImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr());
576 
577 				if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceImage.getAccess(), resultImage, Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
578 					TCU_FAIL("Rendered image is not correct" + (params.early_and_late ? (" for OpExecutionMode: " + ExecutionModeStencil[stencilModeNdx]) : ""));
579 			}
580 		}
581 	}
582 	return tcu::TestStatus::pass("OK");
583 }
584 
checkSupport(Context & context,TestParams params)585 void checkSupport (Context& context, TestParams params)
586 {
587 	context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
588 
589 	if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.stencilFormat))
590 		TCU_THROW(NotSupportedError, "Image format not supported");
591 
592 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType);
593 
594 #ifndef CTS_USES_VULKANSC
595 	if (params.early_and_late)
596 	{
597 		context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
598 		if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
599 			TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
600 	}
601 #endif
602 }
603 
604 } // anonymous
605 
createStencilExportTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)606 tcu::TestCaseGroup* createStencilExportTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
607 {
608 	struct
609 	{
610 		const vk::VkFormat	format;
611 		const std::string	name;
612 	} kFormats[] =
613 	{
614 		{ vk::VK_FORMAT_S8_UINT,			"s8_uint"				},
615 		{ vk::VK_FORMAT_D24_UNORM_S8_UINT,	"d24_unorm_s8_uint"		},
616 		{ vk::VK_FORMAT_D32_SFLOAT_S8_UINT,	"d32_sfloat_s8_uint"	},
617 	};
618 
619 	TestParams params
620 	{
621 		pipelineConstructionType,
622 		vk::VK_FORMAT_S8_UINT,
623 		false
624 	};
625 
626 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_stencil_export", ""));
627 	for (int fmtIdx = 0; fmtIdx < DE_LENGTH_OF_ARRAY(kFormats); ++fmtIdx)
628 	{
629 		params.stencilFormat = kFormats[fmtIdx].format;
630 		de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, kFormats[fmtIdx].name.c_str(), ""));
631 		addFunctionCaseWithPrograms(formatGroup.get(), "op_replace", "", checkSupport, initPrograms, testStencilExportReplace, params);
632 #ifndef CTS_USES_VULKANSC
633 		params.early_and_late = true;
634 		addFunctionCaseWithPrograms(formatGroup.get(), "op_replace_early_and_late", "", checkSupport, initPrograms, testStencilExportReplace, params);
635 		params.early_and_late = false;
636 #endif
637 		group->addChild(formatGroup.release());
638 	}
639 	return group.release();
640 }
641 
642 } // pipeline
643 } // vkt
644