• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022,2023 The Khronos Group Inc.
6  * Copyright (c) 2022,2023 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file vktDrawSampleAttributeTests.cpp
22  * \brief Tests for the sample interpolation attribute
23  *//*--------------------------------------------------------------------*/
24 
25 #include "tcuStringTemplate.hpp"
26 #include "vkCmdUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vktDrawBaseClass.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 
34 #include "vkPipelineConstructionUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 
37 #include "vkDefs.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "vkImageUtil.hpp"
40 #include "deStringUtil.hpp"
41 #include "vktTestCaseUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 #include "vkImageWithMemory.hpp"
46 #include "vkBarrierUtil.hpp"
47 #include "vkBufferWithMemory.hpp"
48 #include "vkBuilderUtil.hpp"
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 namespace
55 {
56 
57 using namespace vk;
58 
59 enum class Trigger
60 {
61 	SAMPLE_ID_STATIC_USE = 0,
62 	SAMPLE_POSITION_STATIC_USE,
63 	SAMPLE_DECORATION_DYNAMIC_USE,
64 };
65 
66 struct TestParameters
67 {
68 	const SharedGroupParams	general;
69 
70 	// Test case variant on the fragment shader.
71 	Trigger					trigger;
72 };
73 
74 /*
75  * Test that sample interpolation correctly enables sample shading at a rate of 1.0
76  */
77 class SampleShadingSampleAttributeTestCase : public vkt::TestCase
78 {
79 public:
80 	SampleShadingSampleAttributeTestCase    (tcu::TestContext& context, const std::string& name, const TestParameters& params);
81 	void            initPrograms            (SourceCollections& programCollection) const override;
82 	TestInstance*   createInstance          (Context& context) const override;
83 	void            checkSupport            (Context& context) const override;
84 
85 private:
86 	const TestParameters m_params;
87 };
88 
89 class SampleShadingSampleAttributeTestInstance : public vkt::TestInstance
90 {
91 public:
92 	SampleShadingSampleAttributeTestInstance (Context& context, const TestParameters& params);
93 	tcu::TestStatus iterate                  (void) override;
94 
95 private:
96 	const TestParameters m_params;
97 
98 	static constexpr uint32_t				width			= 4u;
99 	static constexpr uint32_t				height			= 4u;
100 	static constexpr VkSampleCountFlagBits	sampleCount		= VK_SAMPLE_COUNT_4_BIT;
101 	static constexpr uint32_t				expectedCounter	= sampleCount * width * height;
102 };
103 
SampleShadingSampleAttributeTestCase(tcu::TestContext & context,const std::string & name,const TestParameters & params)104 SampleShadingSampleAttributeTestCase::SampleShadingSampleAttributeTestCase(tcu::TestContext& context, const std::string& name, const TestParameters& params):
105 	vkt::TestCase(context, name), m_params(params) { }
106 
checkSupport(Context & context) const107 void SampleShadingSampleAttributeTestCase::checkSupport(Context& context) const
108 {
109 	if (m_params.general->useDynamicRendering)
110 		context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
111 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
112 }
113 
initPrograms(SourceCollections & collection) const114 void SampleShadingSampleAttributeTestCase::initPrograms(SourceCollections& collection) const
115 {
116 	const bool sampleFragInput			= (m_params.trigger == Trigger::SAMPLE_DECORATION_DYNAMIC_USE);
117 	const bool declareSampleId			= (m_params.trigger == Trigger::SAMPLE_ID_STATIC_USE);
118 	const bool declareSamplePosition	= (m_params.trigger == Trigger::SAMPLE_POSITION_STATIC_USE);
119 
120 	{
121 		std::ostringstream src;
122 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
123 			<< "vec2 positions[3] = vec2[](\n"
124 			<< "    vec2(-1.0, -1.0),\n"
125 			<< "    vec2(3.0, -1.0),\n"
126 			<< "    vec2(-1.0, 3.0)\n"
127 			<< ");\n"
128 			<< (sampleFragInput ? "layout (location = 0) out float verify;\n" : "")
129 			<< "void main() {\n"
130 			<< "    const uint triIdx     = gl_VertexIndex / 3u;\n"											// In practice this will always be zero.
131 			<< "    const uint triVertIdx = gl_VertexIndex % 3u;\n"
132 			<< "    gl_Position = vec4(positions[triVertIdx], 0.0, 1.0);\n"
133 			<< (sampleFragInput ? "    verify = float(triIdx) + float(triVertIdx) / 16.0 + 0.75;\n" : "")	// In practice a number between 0.75 and 1.0.
134 			<< "}\n";
135 		collection.glslSources.add("vert") << glu::VertexSource(src.str());
136 	}
137 
138 	{
139 		std::ostringstream src;
140 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
141 			<< "layout (location = 0) out vec4 outColor;\n"
142 			<< (sampleFragInput ? "layout (location = 0) sample in float verify;\n" : "")
143 			<< "layout (std430, binding = 0) buffer Output {\n"
144 			<< "    uint invocationCount;\n"
145 			<< "} buf;\n"
146 			<< "void main() {\n"
147 			<< (declareSampleId ? "    gl_SampleID;\n" : "")
148 			<< (declareSamplePosition ? "    gl_SamplePosition;\n" : "")
149 			<< "    uint one   = " << (sampleFragInput ? "uint(ceil(verify))" : "1") << ";\n"
150 			<< "    uint index = atomicAdd(buf.invocationCount, one);\n"
151 			<< "    outColor = vec4(float(one), 1.0, 0.0, 1.0);\n"
152 			<< "}\n";
153 		collection.glslSources.add("frag") << glu::FragmentSource(src.str());
154 	}
155 }
156 
createInstance(Context & context) const157 TestInstance* SampleShadingSampleAttributeTestCase::createInstance(Context& context) const
158 {
159 	return new SampleShadingSampleAttributeTestInstance(context, m_params);
160 }
161 
SampleShadingSampleAttributeTestInstance(Context & context,const TestParameters & params)162 SampleShadingSampleAttributeTestInstance::SampleShadingSampleAttributeTestInstance(Context& context, const TestParameters& params) : vkt::TestInstance(context), m_params(params) { }
163 
iterate(void)164 tcu::TestStatus SampleShadingSampleAttributeTestInstance::iterate(void)
165 {
166 	const auto ctx = m_context.getContextCommonData();
167 
168 	// Verification buffer.
169 	const auto			bufferSize		= static_cast<VkDeviceSize>(sizeof(uint32_t));
170 	BufferWithMemory	buffer			(ctx.vkd, ctx.device, ctx.allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
171 	auto&				bufferAlloc		= buffer.getAllocation();
172 	void*				bufferData		= bufferAlloc.getHostPtr();
173 
174 	deMemset(bufferData, 0, static_cast<size_t>(bufferSize));
175 	flushAlloc(ctx.vkd, ctx.device, bufferAlloc);
176 
177 	// Color attachment.
178 	const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
179 	const auto imageExtent = makeExtent3D(width, height, 1u);
180 
181 	const std::vector<VkViewport>	viewports	{ makeViewport(imageExtent) };
182 	const std::vector<VkRect2D>		scissors	{ makeRect2D(imageExtent) };
183 
184 	const auto subresourceRange	= makeDefaultImageSubresourceRange();
185 	const auto imageUsage		= static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
186 
187 	const VkImageCreateInfo imageCreateInfo =
188 	{
189 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		//	VkStructureType				sType;
190 		nullptr,									//	const void*					pNext;
191 		0u,											//	VkImageCreateFlags			flags;
192 		VK_IMAGE_TYPE_2D,							//	VkImageType					imageType;
193 		imageFormat,								//	VkFormat					format;
194 		imageExtent,								//	VkExtent3D					extent;
195 		1u,											//	deUint32					mipLevels;
196 		1u,											//	deUint32					arrayLayers;
197 		sampleCount,								//	VkSampleCountFlagBits		samples;
198 		VK_IMAGE_TILING_OPTIMAL,					//	VkImageTiling				tiling;
199 		imageUsage,									//	VkImageUsageFlags			usage;
200 		VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode				sharingMode;
201 		0u,											//	deUint32					queueFamilyIndexCount;
202 		nullptr,									//	const deUint32*				pQueueFamilyIndices;
203 		VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout				initialLayout;
204 	};
205 
206 	ImageWithMemory colorAttachment		(ctx.vkd, ctx.device, ctx.allocator, imageCreateInfo, MemoryRequirement::Any);
207 	const auto		colorAttachmentView	= makeImageView(ctx.vkd, ctx.device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
208 
209 	// Structures used for renderpasses and dynamic rendering.
210 	RenderPassCreateInfo renderPassCreateInfo;
211 
212 	const VkAttachmentReference	colorAttachmentReference =
213 	{
214 		0,
215 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
216 	};
217 
218 	renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
219 															 sampleCount,
220 															 VK_ATTACHMENT_LOAD_OP_CLEAR,
221 															 VK_ATTACHMENT_STORE_OP_STORE,
222 															 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
223 															 VK_ATTACHMENT_STORE_OP_DONT_CARE,
224 															 VK_IMAGE_LAYOUT_UNDEFINED,
225 															 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
226 
227 	renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
228 													   0,
229 													   0,
230 													   nullptr,
231 													   1,
232 													   &colorAttachmentReference,
233 													   nullptr,
234 													   AttachmentReference(),
235 													   0,
236 													   nullptr));
237 
238 	// Render pass and framebuffer.
239 	const auto renderPass		= createRenderPass(ctx.vkd, ctx.device, &renderPassCreateInfo);
240 	const auto framebuffer		= makeFramebuffer(ctx.vkd, ctx.device, renderPass.get(), colorAttachmentView.get(), imageExtent.width, imageExtent.height);
241 	const auto clearValueColor	= makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
242 
243 #ifndef CTS_USES_VULKANSC
244 	const VkRenderingAttachmentInfoKHR colorAttachments =
245 	{
246 		VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
247 		nullptr,											// const void*							pNext;
248 		colorAttachmentView.get(),							// VkImageView							imageView;
249 		VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,				// VkImageLayout						imageLayout;
250 		VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
251 		VK_NULL_HANDLE,										// VkImageView							resolveImageView;
252 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						resolveImageLayout;
253 		VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp					loadOp;
254 		VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
255 		clearValueColor										// VkClearValue							clearValue;
256 	};
257 
258 	const auto renderInfoFlags = (
259 		(m_params.general->useDynamicRendering
260 		 && !m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass
261 		 && m_params.general->useSecondaryCmdBuffer)
262 		 ? static_cast<VkRenderingFlags>(VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT)
263 		 : 0u);
264 
265 	const VkRenderingInfoKHR	renderInfo		=
266 	{
267 		VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,	// VkStructureType                     sType;
268 		0,										// const void*                         pNext;
269 		renderInfoFlags,						// VkRenderingFlags                    flags;
270 		scissors.at(0),							// VkRect2D                            renderArea;
271 		1,										// uint32_t                            layerCount;
272 		0,										// uint32_t                            viewMask;
273 		1,										// uint32_t                            colorAttachmentCount;
274 		&colorAttachments,						// const VkRenderingAttachmentInfo*    pColorAttachments;
275 		VK_NULL_HANDLE,							// const VkRenderingAttachmentInfo*    pDepthAttachment;
276 		VK_NULL_HANDLE							// const VkRenderingAttachmentInfo*    pStencilAttachment;
277 	};
278 
279 	const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
280 	{
281 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType					sType;
282 		nullptr,															// const void*						pNext;
283 		0,																	// VkRenderingFlagsKHR				flags;
284 		0u,																	// uint32_t							viewMask;
285 		1u,																	// uint32_t							colorAttachmentCount;
286 		&imageFormat,														// const VkFormat*					pColorAttachmentFormats;
287 		VK_FORMAT_UNDEFINED,												// VkFormat							depthAttachmentFormat;
288 		VK_FORMAT_UNDEFINED,												// VkFormat							stencilAttachmentFormat;
289 		sampleCount,														// VkSampleCountFlagBits			rasterizationSamples;
290 	};
291 
292 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo
293 	{
294 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,					// VkStructureType					sType;
295 		&inheritanceRenderingInfo,											// const void*						pNext;
296 		VK_NULL_HANDLE,														// VkRenderPass						renderPass;
297 		0u,																	// deUint32							subpass;
298 		VK_NULL_HANDLE,														// VkFramebuffer					framebuffer;
299 		VK_FALSE,															// VkBool32							occlusionQueryEnable;
300 		(VkQueryControlFlags)0u,											// VkQueryControlFlags				queryFlags;
301 		(VkQueryPipelineStatisticFlags)0u									// VkQueryPipelineStatisticFlags	pipelineStatistics;
302 	};
303 #endif
304 
305 	DescriptorSetLayoutBuilder layoutBuilder;
306 	layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
307 
308 	const auto descriptorSetLayout    = layoutBuilder.build(ctx.vkd, ctx.device);
309 	const auto graphicsPipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, descriptorSetLayout.get());
310 
311 	DescriptorPoolBuilder poolBuilder;
312 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
313 	const auto descriptorPool = poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
314 	const auto descriptorSetBuffer		= makeDescriptorSet(ctx.vkd, ctx.device, descriptorPool.get(), descriptorSetLayout.get());
315 
316 	// Update descriptor sets.
317 	const auto bufferInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, bufferSize);
318 
319 	DescriptorSetUpdateBuilder updater;
320 	updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
321 	updater.update(ctx.vkd, ctx.device);
322 
323 	const auto vtxshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("vert"));
324 	const auto frgshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("frag"));
325 
326 	const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
327 
328 	// Set up a default multisample state that doesn't use sample shading and with minSampleShading set to 0.0.
329 	VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
330 	multisampling.sampleShadingEnable	= VK_FALSE;
331 	multisampling.minSampleShading		= 0.0;
332 	multisampling.rasterizationSamples	= sampleCount;
333 
334 	const auto pass		= (m_params.general->useDynamicRendering ? VK_NULL_HANDLE : renderPass.get());
335 	const auto pipeline	= makeGraphicsPipeline(
336 		ctx.vkd,								// const DeviceInterface&                 vk
337 		ctx.device,								// const VkDevice                         device
338 		graphicsPipelineLayout.get(),			// const VkPipelineLayout                 pipelineLayout
339 		*vtxshader,								// const VkShaderModule                   vertexShaderModule
340 		VK_NULL_HANDLE,							// const VkShaderModule                   tessellationControlModule
341 		VK_NULL_HANDLE,							// const VkShaderModule                   tessellationEvalModule
342 		VK_NULL_HANDLE,							// const VkShaderModule                   geometryShaderModule
343 		*frgshader,								// const VkShaderModule                   fragmentShaderModule
344 		pass,									// const VkRenderPass                     renderPass
345 		viewports,								// const std::vector<VkViewport>&         viewports
346 		scissors,								// const std::vector<VkRect2D>&           scissors
347 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology              topology
348 		0u,										// const deUint32                         subpass
349 		0u,										// const deUint32                         patchControlPoints
350 		&vertexInputState,						// VkPipelineVertexInputStateCreateInfo   *vertexInputStateCreateInfo
351 		VK_NULL_HANDLE,							// VkPipelineRasterizationStateCreateInfo *rasterizationStateCreateInfo
352 		&multisampling							// VkPipelineMultisampleStateCreateInfo   *multisampleStateCreateInfo
353 	);
354 
355 	const auto commandPool				= createCommandPool(ctx.vkd, ctx.device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, ctx.qfIndex);
356 	const auto primaryCmdBufferPtr		= allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
357 	const auto primaryCmdBuffer			= *primaryCmdBufferPtr;
358 #ifndef CTS_USES_VULKANSC
359 	const auto secondaryCmdBufferPtr	= allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
360 	const auto secondaryCmdBuffer		= *secondaryCmdBufferPtr;
361 #endif // CTS_USES_VULKANSC
362 
363 	beginCommandBuffer(ctx.vkd, primaryCmdBuffer);
364 
365 	if (m_params.general->useDynamicRendering)
366 	{
367 #ifndef CTS_USES_VULKANSC
368 		// Transition color attachment to the proper layout.
369 		const auto initialBarrier = makeImageMemoryBarrier(
370 			0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
371 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,
372 			colorAttachment.get(), subresourceRange);
373 		cmdPipelineImageMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &initialBarrier);
374 
375 		if (m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
376 		{
377 			const VkCommandBufferUsageFlags	usageFlags				= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
378 			const VkCommandBufferBeginInfo	commandBufBeginParams	=
379 			{
380 				VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
381 				nullptr,												// const void*						pNext;
382 				usageFlags,												// VkCommandBufferUsageFlags		flags;
383 				&bufferInheritanceInfo
384 			};
385 
386 			ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
387 			ctx.vkd.cmdBeginRendering(secondaryCmdBuffer, &renderInfo);
388 			ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
389 			ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
390 			ctx.vkd.cmdDraw(secondaryCmdBuffer, 3u, 1u, 0u, 0u);
391 			ctx.vkd.cmdEndRendering(secondaryCmdBuffer);
392 			endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
393 			ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
394 		}
395 		else if (!m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass && m_params.general->useSecondaryCmdBuffer)
396 		{
397 			const VkCommandBufferUsageFlags	usageFlags				= (VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
398 			const VkCommandBufferBeginInfo	commandBufBeginParams	=
399 			{
400 				VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// VkStructureType					sType;
401 				nullptr,												// const void*						pNext;
402 				usageFlags,												// VkCommandBufferUsageFlags		flags;
403 				&bufferInheritanceInfo
404 			};
405 
406 			ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
407 			ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
408 			ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
409 			ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
410 			ctx.vkd.cmdDraw(secondaryCmdBuffer, 3, 1, 0, 0);
411 			endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
412 			ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
413 			ctx.vkd.cmdEndRendering(primaryCmdBuffer);
414 		}
415 		else
416 		{
417 			ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
418 			ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
419 			ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
420 			ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
421 			ctx.vkd.cmdEndRendering(primaryCmdBuffer);
422 		}
423 #else
424 	DE_ASSERT(false);
425 #endif
426 	}
427 	else
428 	{
429 		const VkRenderPassBeginInfo renderPassBeginInfo =
430 		{
431 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			// VkStructureType         sType;
432 			nullptr,											// const void*             pNext;
433 			*renderPass,										// VkRenderPass            renderPass;
434 			*framebuffer,										// VkFramebuffer           framebuffer;
435 			scissors.at(0),										// VkRect2D                renderArea;
436 			1,													// uint32_t                clearValueCount;
437 			&clearValueColor,									// const VkClearValue*     pClearValues;
438 		};
439 		ctx.vkd.cmdBeginRenderPass(primaryCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
440 		ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
441 		ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
442 		ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
443 		ctx.vkd.cmdEndRenderPass(primaryCmdBuffer);
444 	}
445 
446 	const VkBufferMemoryBarrier renderBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer.get(), 0ull, bufferSize);
447 	cmdPipelineBufferMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &renderBufferBarrier);
448 	endCommandBuffer(ctx.vkd, primaryCmdBuffer);
449 	submitCommandsAndWait(ctx.vkd, ctx.device, m_context.getUniversalQueue(), primaryCmdBuffer);
450 
451 	invalidateAlloc(ctx.vkd, ctx.device, bufferAlloc);
452 
453 	uint32_t result = 0;
454 	deMemcpy(&result, bufferData, sizeof(result));
455 
456 	if (result < expectedCounter)
457 	{
458 		std::stringstream output;
459 		output << "Atomic counter value lower than expected: " << result;
460 		return tcu::TestStatus::fail(output.str());
461 	}
462 
463 	return tcu::TestStatus::pass("Pass");
464 }
465 
466 } // anonoymous
467 
createSampleAttributeTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)468 tcu::TestCaseGroup* createSampleAttributeTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
469 {
470 	const struct
471 	{
472 		Trigger		trigger;
473 		const char*	name;
474 	} triggerCases[] =
475 	{
476 		// Dynamically use the sample decoration on a frag shader input variable
477 		{ Trigger::SAMPLE_DECORATION_DYNAMIC_USE,	"sample_decoration_dynamic_use"},
478 		// Declare SampleId built-in in the frag shader without using it
479 		{ Trigger::SAMPLE_ID_STATIC_USE,			"sample_id_static_use"},
480 		// Declare SamplePosition built-in in the frag shader without using it
481 		{ Trigger::SAMPLE_POSITION_STATIC_USE,		"sample_position_static_use"},
482 	};
483 
484 	de::MovePtr<tcu::TestCaseGroup> group {new tcu::TestCaseGroup{testCtx, "implicit_sample_shading"}};
485 
486 	for (const auto& triggerCase : triggerCases)
487 	{
488 		const TestParameters params { groupParams, triggerCase.trigger };
489 		group->addChild(new SampleShadingSampleAttributeTestCase(testCtx, triggerCase.name, params));
490 	}
491 
492 	return group.release();
493 }
494 
495 } // Draw
496 } // vkt
497