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