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,
81 const TestParameters ¶ms);
82 void initPrograms(SourceCollections &programCollection) const override;
83 TestInstance *createInstance(Context &context) const override;
84 void checkSupport(Context &context) const override;
85
86 private:
87 const TestParameters m_params;
88 };
89
90 class SampleShadingSampleAttributeTestInstance : public vkt::TestInstance
91 {
92 public:
93 SampleShadingSampleAttributeTestInstance(Context &context, const TestParameters ¶ms);
94 tcu::TestStatus iterate(void) override;
95
96 private:
97 const TestParameters m_params;
98
99 static constexpr uint32_t width = 4u;
100 static constexpr uint32_t height = 4u;
101 static constexpr VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
102 static constexpr uint32_t expectedCounter = sampleCount * width * height;
103 };
104
SampleShadingSampleAttributeTestCase(tcu::TestContext & context,const std::string & name,const TestParameters & params)105 SampleShadingSampleAttributeTestCase::SampleShadingSampleAttributeTestCase(tcu::TestContext &context,
106 const std::string &name,
107 const TestParameters ¶ms)
108 : vkt::TestCase(context, name)
109 , m_params(params)
110 {
111 }
112
checkSupport(Context & context) const113 void SampleShadingSampleAttributeTestCase::checkSupport(Context &context) const
114 {
115 const bool declareSampleId = (m_params.trigger == Trigger::SAMPLE_ID_STATIC_USE);
116 const bool declareSamplePosition = (m_params.trigger == Trigger::SAMPLE_POSITION_STATIC_USE);
117
118 if (m_params.general->useDynamicRendering)
119 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
120 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
121
122 if (declareSampleId || declareSamplePosition)
123 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
124 }
125
initPrograms(SourceCollections & collection) const126 void SampleShadingSampleAttributeTestCase::initPrograms(SourceCollections &collection) const
127 {
128 const bool sampleFragInput = (m_params.trigger == Trigger::SAMPLE_DECORATION_DYNAMIC_USE);
129 const bool declareSampleId = (m_params.trigger == Trigger::SAMPLE_ID_STATIC_USE);
130 const bool declareSamplePosition = (m_params.trigger == Trigger::SAMPLE_POSITION_STATIC_USE);
131
132 {
133 std::ostringstream src;
134 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
135 << "vec2 positions[3] = vec2[](\n"
136 << " vec2(-1.0, -1.0),\n"
137 << " vec2(3.0, -1.0),\n"
138 << " vec2(-1.0, 3.0)\n"
139 << ");\n"
140 << (sampleFragInput ? "layout (location = 0) out float verify;\n" : "") << "void main() {\n"
141 << " const uint triIdx = gl_VertexIndex / 3u;\n" // In practice this will always be zero.
142 << " const uint triVertIdx = gl_VertexIndex % 3u;\n"
143 << " gl_Position = vec4(positions[triVertIdx], 0.0, 1.0);\n"
144 << (sampleFragInput ? " verify = float(triIdx) + float(triVertIdx) / 16.0 + 0.75;\n" :
145 "") // In practice a number between 0.75 and 1.0.
146 << "}\n";
147 collection.glslSources.add("vert") << glu::VertexSource(src.str());
148 }
149
150 {
151 std::ostringstream src;
152 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
153 << "layout (location = 0) out vec4 outColor;\n"
154 << (sampleFragInput ? "layout (location = 0) sample in float verify;\n" : "")
155 << "layout (std430, binding = 0) buffer Output {\n"
156 << " uint invocationCount;\n"
157 << "} buf;\n"
158 << "void main() {\n"
159 << (declareSampleId ? " gl_SampleID;\n" : "")
160 << (declareSamplePosition ? " gl_SamplePosition;\n" : "")
161 << " uint one = " << (sampleFragInput ? "uint(ceil(verify))" : "1") << ";\n"
162 << " uint index = atomicAdd(buf.invocationCount, one);\n"
163 << " outColor = vec4(float(one), 1.0, 0.0, 1.0);\n"
164 << "}\n";
165 collection.glslSources.add("frag") << glu::FragmentSource(src.str());
166 }
167 }
168
createInstance(Context & context) const169 TestInstance *SampleShadingSampleAttributeTestCase::createInstance(Context &context) const
170 {
171 return new SampleShadingSampleAttributeTestInstance(context, m_params);
172 }
173
SampleShadingSampleAttributeTestInstance(Context & context,const TestParameters & params)174 SampleShadingSampleAttributeTestInstance::SampleShadingSampleAttributeTestInstance(Context &context,
175 const TestParameters ¶ms)
176 : vkt::TestInstance(context)
177 , m_params(params)
178 {
179 }
180
iterate(void)181 tcu::TestStatus SampleShadingSampleAttributeTestInstance::iterate(void)
182 {
183 const auto ctx = m_context.getContextCommonData();
184
185 // Verification buffer.
186 const auto bufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
187 BufferWithMemory buffer(ctx.vkd, ctx.device, ctx.allocator,
188 makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
189 MemoryRequirement::HostVisible);
190 auto &bufferAlloc = buffer.getAllocation();
191 void *bufferData = bufferAlloc.getHostPtr();
192
193 deMemset(bufferData, 0, static_cast<size_t>(bufferSize));
194 flushAlloc(ctx.vkd, ctx.device, bufferAlloc);
195
196 // Color attachment.
197 const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
198 const auto imageExtent = makeExtent3D(width, height, 1u);
199
200 const std::vector<VkViewport> viewports{makeViewport(imageExtent)};
201 const std::vector<VkRect2D> scissors{makeRect2D(imageExtent)};
202
203 const auto subresourceRange = makeDefaultImageSubresourceRange();
204 const auto imageUsage =
205 static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
206
207 const VkImageCreateInfo imageCreateInfo = {
208 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
209 nullptr, // const void* pNext;
210 0u, // VkImageCreateFlags flags;
211 VK_IMAGE_TYPE_2D, // VkImageType imageType;
212 imageFormat, // VkFormat format;
213 imageExtent, // VkExtent3D extent;
214 1u, // uint32_t mipLevels;
215 1u, // uint32_t arrayLayers;
216 sampleCount, // VkSampleCountFlagBits samples;
217 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
218 imageUsage, // VkImageUsageFlags usage;
219 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
220 0u, // uint32_t queueFamilyIndexCount;
221 nullptr, // const uint32_t* pQueueFamilyIndices;
222 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
223 };
224
225 ImageWithMemory colorAttachment(ctx.vkd, ctx.device, ctx.allocator, imageCreateInfo, MemoryRequirement::Any);
226 const auto colorAttachmentView =
227 makeImageView(ctx.vkd, ctx.device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
228
229 // Structures used for renderpasses and dynamic rendering.
230 RenderPassCreateInfo renderPassCreateInfo;
231
232 const VkAttachmentReference colorAttachmentReference = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
233
234 renderPassCreateInfo.addAttachment(
235 AttachmentDescription(imageFormat, sampleCount, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
236 VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
237 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
238
239 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, nullptr, 1,
240 &colorAttachmentReference, nullptr, AttachmentReference(), 0,
241 nullptr));
242
243 // Render pass and framebuffer.
244 const auto renderPass = createRenderPass(ctx.vkd, ctx.device, &renderPassCreateInfo);
245 const auto framebuffer = makeFramebuffer(ctx.vkd, ctx.device, renderPass.get(), colorAttachmentView.get(),
246 imageExtent.width, imageExtent.height);
247 const auto clearValueColor = makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
248
249 #ifndef CTS_USES_VULKANSC
250 const VkRenderingAttachmentInfoKHR colorAttachments = {
251 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
252 nullptr, // const void* pNext;
253 colorAttachmentView.get(), // VkImageView imageView;
254 VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout imageLayout;
255 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
256 VK_NULL_HANDLE, // VkImageView resolveImageView;
257 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout resolveImageLayout;
258 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
259 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
260 clearValueColor // VkClearValue clearValue;
261 };
262
263 const auto renderInfoFlags =
264 ((m_params.general->useDynamicRendering &&
265 !m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass &&
266 m_params.general->useSecondaryCmdBuffer) ?
267 static_cast<VkRenderingFlags>(VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT) :
268 0u);
269
270 const VkRenderingInfoKHR renderInfo = {
271 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType sType;
272 0, // const void* pNext;
273 renderInfoFlags, // VkRenderingFlags flags;
274 scissors.at(0), // VkRect2D renderArea;
275 1, // uint32_t layerCount;
276 0, // uint32_t viewMask;
277 1, // uint32_t colorAttachmentCount;
278 &colorAttachments, // const VkRenderingAttachmentInfo* pColorAttachments;
279 VK_NULL_HANDLE, // const VkRenderingAttachmentInfo* pDepthAttachment;
280 VK_NULL_HANDLE // const VkRenderingAttachmentInfo* pStencilAttachment;
281 };
282
283 const VkPipelineRenderingCreateInfoKHR pipelineRenderInfo = {
284 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, // VkStructureType sType;
285 DE_NULL, // const void* pNext;
286 0, // uint32_t viewMask;
287 1, // uint32_t colorAttachmentCount;
288 &imageFormat, // const VkFormat* pColorAttachmentFormats;
289 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
290 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
291 };
292 const auto *gpPNext = &pipelineRenderInfo;
293
294 const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
295 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
296 nullptr, // const void* pNext;
297 0, // VkRenderingFlagsKHR flags;
298 0u, // uint32_t viewMask;
299 1u, // uint32_t colorAttachmentCount;
300 &imageFormat, // const VkFormat* pColorAttachmentFormats;
301 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
302 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
303 sampleCount, // VkSampleCountFlagBits rasterizationSamples;
304 };
305
306 const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
307 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
308 &inheritanceRenderingInfo, // const void* pNext;
309 VK_NULL_HANDLE, // VkRenderPass renderPass;
310 0u, // uint32_t subpass;
311 VK_NULL_HANDLE, // VkFramebuffer framebuffer;
312 VK_FALSE, // VkBool32 occlusionQueryEnable;
313 (VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
314 (VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
315 };
316 #else
317 const void *gpPNext = nullptr;
318 #endif
319
320 DescriptorSetLayoutBuilder layoutBuilder;
321 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
322
323 const auto descriptorSetLayout = layoutBuilder.build(ctx.vkd, ctx.device);
324 const auto graphicsPipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, descriptorSetLayout.get());
325
326 DescriptorPoolBuilder poolBuilder;
327 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
328 const auto descriptorPool =
329 poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
330 const auto descriptorSetBuffer =
331 makeDescriptorSet(ctx.vkd, ctx.device, descriptorPool.get(), descriptorSetLayout.get());
332
333 // Update descriptor sets.
334 const auto bufferInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, bufferSize);
335
336 DescriptorSetUpdateBuilder updater;
337 updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
338 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
339 updater.update(ctx.vkd, ctx.device);
340
341 const auto vtxshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("vert"));
342 const auto frgshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("frag"));
343
344 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
345
346 // Set up a default multisample state that doesn't use sample shading and with minSampleShading set to 0.0.
347 VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
348 multisampling.sampleShadingEnable = VK_FALSE;
349 multisampling.minSampleShading = 0.0;
350 multisampling.rasterizationSamples = sampleCount;
351
352 const auto pass = (m_params.general->useDynamicRendering ? VK_NULL_HANDLE : renderPass.get());
353 const auto pipeline = makeGraphicsPipeline(
354 ctx.vkd, // const DeviceInterface& vk
355 ctx.device, // const VkDevice device
356 graphicsPipelineLayout.get(), // const VkPipelineLayout pipelineLayout
357 *vtxshader, // const VkShaderModule vertexShaderModule
358 VK_NULL_HANDLE, // const VkShaderModule tessellationControlModule
359 VK_NULL_HANDLE, // const VkShaderModule tessellationEvalModule
360 VK_NULL_HANDLE, // const VkShaderModule geometryShaderModule
361 *frgshader, // const VkShaderModule fragmentShaderModule
362 pass, // const VkRenderPass renderPass
363 viewports, // const std::vector<VkViewport>& viewports
364 scissors, // const std::vector<VkRect2D>& scissors
365 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
366 0u, // const uint32_t subpass
367 0u, // const uint32_t patchControlPoints
368 &vertexInputState, // VkPipelineVertexInputStateCreateInfo *vertexInputStateCreateInfo
369 VK_NULL_HANDLE, // VkPipelineRasterizationStateCreateInfo *rasterizationStateCreateInfo
370 &multisampling, // VkPipelineMultisampleStateCreateInfo *multisampleStateCreateInfo
371 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
372 DE_NULL, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
373 DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
374 gpPNext // const void* pNext
375 );
376
377 const auto commandPool = createCommandPool(ctx.vkd, ctx.device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, ctx.qfIndex);
378 const auto primaryCmdBufferPtr =
379 allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
380 const auto primaryCmdBuffer = *primaryCmdBufferPtr;
381 #ifndef CTS_USES_VULKANSC
382 const auto secondaryCmdBufferPtr =
383 allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
384 const auto secondaryCmdBuffer = *secondaryCmdBufferPtr;
385 #endif // CTS_USES_VULKANSC
386
387 beginCommandBuffer(ctx.vkd, primaryCmdBuffer);
388
389 if (m_params.general->useDynamicRendering)
390 {
391 #ifndef CTS_USES_VULKANSC
392 // Transition color attachment to the proper layout.
393 const auto initialBarrier =
394 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
395 VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, colorAttachment.get(), subresourceRange);
396 cmdPipelineImageMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
397 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &initialBarrier);
398
399 if (m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
400 {
401 const VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
402 const VkCommandBufferBeginInfo commandBufBeginParams = {
403 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
404 nullptr, // const void* pNext;
405 usageFlags, // VkCommandBufferUsageFlags flags;
406 &bufferInheritanceInfo};
407
408 ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
409 ctx.vkd.cmdBeginRendering(secondaryCmdBuffer, &renderInfo);
410 ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
411 graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
412 ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
413 ctx.vkd.cmdDraw(secondaryCmdBuffer, 3u, 1u, 0u, 0u);
414 ctx.vkd.cmdEndRendering(secondaryCmdBuffer);
415 endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
416 ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
417 }
418 else if (!m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass &&
419 m_params.general->useSecondaryCmdBuffer)
420 {
421 const VkCommandBufferUsageFlags usageFlags =
422 (VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
423 const VkCommandBufferBeginInfo commandBufBeginParams = {
424 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
425 nullptr, // const void* pNext;
426 usageFlags, // VkCommandBufferUsageFlags flags;
427 &bufferInheritanceInfo};
428
429 ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
430 ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
431 ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
432 graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
433 ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
434 ctx.vkd.cmdDraw(secondaryCmdBuffer, 3, 1, 0, 0);
435 endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
436 ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
437 ctx.vkd.cmdEndRendering(primaryCmdBuffer);
438 }
439 else
440 {
441 ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
442 ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
443 graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
444 ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
445 ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
446 ctx.vkd.cmdEndRendering(primaryCmdBuffer);
447 }
448 #else
449 DE_ASSERT(false);
450 #endif
451 }
452 else
453 {
454 const VkRenderPassBeginInfo renderPassBeginInfo = {
455 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
456 nullptr, // const void* pNext;
457 *renderPass, // VkRenderPass renderPass;
458 *framebuffer, // VkFramebuffer framebuffer;
459 scissors.at(0), // VkRect2D renderArea;
460 1, // uint32_t clearValueCount;
461 &clearValueColor, // const VkClearValue* pClearValues;
462 };
463 ctx.vkd.cmdBeginRenderPass(primaryCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
464 ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(),
465 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
466 ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
467 ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
468 ctx.vkd.cmdEndRenderPass(primaryCmdBuffer);
469 }
470
471 const VkBufferMemoryBarrier renderBufferBarrier =
472 makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer.get(), 0ull, bufferSize);
473 cmdPipelineBufferMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
474 VK_PIPELINE_STAGE_HOST_BIT, &renderBufferBarrier);
475 endCommandBuffer(ctx.vkd, primaryCmdBuffer);
476 submitCommandsAndWait(ctx.vkd, ctx.device, m_context.getUniversalQueue(), primaryCmdBuffer);
477
478 invalidateAlloc(ctx.vkd, ctx.device, bufferAlloc);
479
480 uint32_t result = 0;
481 deMemcpy(&result, bufferData, sizeof(result));
482
483 if (result < expectedCounter)
484 {
485 std::stringstream output;
486 output << "Atomic counter value lower than expected: " << result;
487 return tcu::TestStatus::fail(output.str());
488 }
489
490 return tcu::TestStatus::pass("Pass");
491 }
492
493 } // namespace
494
createSampleAttributeTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)495 tcu::TestCaseGroup *createSampleAttributeTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
496 {
497 const struct
498 {
499 Trigger trigger;
500 const char *name;
501 } triggerCases[] = {
502 // Dynamically use the sample decoration on a frag shader input variable
503 {Trigger::SAMPLE_DECORATION_DYNAMIC_USE, "sample_decoration_dynamic_use"},
504 // Declare SampleId built-in in the frag shader without using it
505 {Trigger::SAMPLE_ID_STATIC_USE, "sample_id_static_use"},
506 // Declare SamplePosition built-in in the frag shader without using it
507 {Trigger::SAMPLE_POSITION_STATIC_USE, "sample_position_static_use"},
508 };
509
510 de::MovePtr<tcu::TestCaseGroup> group{new tcu::TestCaseGroup{testCtx, "implicit_sample_shading"}};
511
512 for (const auto &triggerCase : triggerCases)
513 {
514 const TestParameters params{groupParams, triggerCase.trigger};
515 group->addChild(new SampleShadingSampleAttributeTestCase(testCtx, triggerCase.name, params));
516 }
517
518 return group.release();
519 }
520
521 } // namespace Draw
522 } // namespace vkt
523