1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 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
22  * \brief VK_AMD_shader_explicit_vertex_parameter tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawExplicitVertexParameterTests.hpp"
26 
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 
37 #include "deDefs.h"
38 #include "deRandom.hpp"
39 #include "deString.h"
40 #include "deMath.h"
41 
42 #include "tcuTestCase.hpp"
43 #include "tcuRGBA.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuStringTemplate.hpp"
47 
48 #include "rrRenderer.hpp"
49 
50 #include <string>
51 #include <sstream>
52 
53 namespace vkt
54 {
55 namespace Draw
56 {
57 namespace
58 {
59 using namespace vk;
60 using namespace std;
61 
62 enum Interpolation
63 {
64     SMOOTH        = 0,
65     NOPERSPECTIVE = 1,
66 };
67 
68 enum AuxiliaryQualifier
69 {
70     AUX_NONE     = 0,
71     AUX_CENTROID = 1,
72     AUX_SAMPLE   = 2,
73 };
74 
75 enum
76 {
77     WIDTH  = 16,
78     HEIGHT = 16
79 };
80 
81 struct PositionValueVertex
82 {
PositionValueVertexvkt::Draw::__anon06b78bc90111::PositionValueVertex83     PositionValueVertex(tcu::Vec4 pos, float val) : position(pos), value(val)
84     {
85     }
86 
87 public:
88     tcu::Vec4 position;
89     float value;
90 };
91 
92 struct DrawParams
93 {
94     Interpolation interpolation;
95     vk::VkSampleCountFlagBits samples;
96     AuxiliaryQualifier auxiliaryStorage;
97     const SharedGroupParams groupParams;
98 };
99 
interpolationToString(Interpolation interpolation)100 const char *interpolationToString(Interpolation interpolation)
101 {
102     switch (interpolation)
103     {
104     case SMOOTH:
105         return "smooth";
106     case NOPERSPECTIVE:
107         return "noperspective";
108     default:
109         DE_FATAL("Invalid interpolation enum");
110     }
111 
112     return "";
113 }
114 
barycentricVariableString(Interpolation interpolation,AuxiliaryQualifier aux)115 std::string barycentricVariableString(Interpolation interpolation, AuxiliaryQualifier aux)
116 {
117     std::ostringstream name;
118     name << "gl_BaryCoord";
119     switch (interpolation)
120     {
121     case SMOOTH:
122         name << "Smooth";
123         break;
124     case NOPERSPECTIVE:
125         name << "NoPersp";
126         break;
127     default:
128         DE_FATAL("Invalid interpolation enum");
129     }
130 
131     switch (aux)
132     {
133     case AUX_CENTROID:
134         name << "Centroid";
135         break;
136     case AUX_SAMPLE:
137         name << "Sample";
138         break;
139     case AUX_NONE:
140         name << "";
141         break;
142     default:
143         DE_FATAL("Invalid auxiliary storage qualifier enum");
144     }
145     name << "AMD";
146     return name.str();
147 }
148 
auxiliaryQualifierToString(AuxiliaryQualifier aux)149 const char *auxiliaryQualifierToString(AuxiliaryQualifier aux)
150 {
151     switch (aux)
152     {
153     case AUX_CENTROID:
154         return "centroid";
155     case AUX_SAMPLE:
156         return "sample";
157     case AUX_NONE:
158         return "";
159     default:
160         DE_FATAL("Invalid auxiliary storage qualifier enum");
161     }
162 
163     return "";
164 }
165 
getTestName(DrawParams params)166 std::string getTestName(DrawParams params)
167 {
168     std::ostringstream name;
169 
170     name << interpolationToString(params.interpolation) << "_";
171 
172     if (params.auxiliaryStorage != AUX_NONE)
173         name << auxiliaryQualifierToString(params.auxiliaryStorage) << "_";
174 
175     name << "samples_" << de::toString(params.samples);
176 
177     return name.str();
178 }
179 
180 class DrawTestInstance : public TestInstance
181 {
182 public:
183     DrawTestInstance(Context &context, const DrawParams &data);
184     ~DrawTestInstance(void);
185     tcu::TestStatus iterate(void);
186 
187 protected:
188     void preRenderCommands(VkCommandBuffer cmdBuffer, VkImage colorTargetImage) const;
189     void beginRenderPass(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue *pClearValues,
190                          uint32_t clearValueCount) const;
191     void drawCommands(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const;
192 
193 #ifndef CTS_USES_VULKANSC
194     void beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
195                                  VkRenderingFlagsKHR renderingFlags = 0u) const;
196     void beginDynamicRender(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue *pClearValues,
197                             VkRenderingFlagsKHR renderingFlags = 0u) const;
198 #endif // CTS_USES_VULKANSC
199 
200 private:
201     DrawParams m_data;
202     Move<VkRenderPass> m_renderPass;
203     Move<VkImageView> m_colorTargetView;
204     Move<VkImageView> m_multisampleTargetView;
205     Move<VkFramebuffer> m_framebuffer;
206     Move<VkPipeline> m_pipeline;
207     Move<VkPipelineLayout> m_pipelineLayout;
208     Move<VkDescriptorPool> m_descriptorPool;
209     Move<VkDescriptorSet> m_descriptorSet;
210     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
211 };
212 
DrawTestInstance(Context & context,const DrawParams & data)213 DrawTestInstance::DrawTestInstance(Context &context, const DrawParams &data) : vkt::TestInstance(context), m_data(data)
214 {
215 }
216 
~DrawTestInstance(void)217 DrawTestInstance::~DrawTestInstance(void)
218 {
219 }
220 
221 class DrawTestCase : public TestCase
222 {
223 public:
224     DrawTestCase(tcu::TestContext &context, const char *name, const DrawParams data);
225     ~DrawTestCase(void);
226     virtual void initPrograms(SourceCollections &programCollection) const;
227     virtual TestInstance *createInstance(Context &context) const;
228     virtual void checkSupport(Context &context) const;
229 
230 private:
231     DrawParams m_data;
232 };
233 
DrawTestCase(tcu::TestContext & context,const char * name,const DrawParams data)234 DrawTestCase::DrawTestCase(tcu::TestContext &context, const char *name, const DrawParams data)
235     : vkt::TestCase(context, name)
236     , m_data(data)
237 {
238 }
239 
~DrawTestCase(void)240 DrawTestCase::~DrawTestCase(void)
241 {
242 }
243 
checkSupport(Context & context) const244 void DrawTestCase::checkSupport(Context &context) const
245 {
246     context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
247 
248     if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
249         TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
250 
251     if (m_data.groupParams->useDynamicRendering)
252         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
253 
254     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
255 }
256 
initPrograms(SourceCollections & programCollection) const257 void DrawTestCase::initPrograms(SourceCollections &programCollection) const
258 {
259     const uint32_t numValues = WIDTH * HEIGHT * m_data.samples;
260 
261     const tcu::StringTemplate vertShader(
262         string("#version 450\n"
263                "#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
264                "\n"
265                "layout(location = 0) in vec4 in_position;\n"
266                "layout(location = 1) in float in_data;\n"
267                "layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
268                "layout(location = 1) ${auxqualifier} ${qualifier}        out float out_data_${qualifier};\n"
269                "\n"
270                "out gl_PerVertex {\n"
271                "    vec4  gl_Position;\n"
272                "    float gl_PointSize;\n"
273                "};\n"
274                "\n"
275                "void main() {\n"
276                "    gl_PointSize              = 1.0;\n"
277                "    gl_Position               = in_position;\n"
278                "    out_data_explicit         = in_data;\n"
279                "    out_data_${qualifier}     = in_data;\n"
280                "}\n"));
281 
282     const tcu::StringTemplate fragShader(
283         string("#version 450\n"
284                "#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
285                "\n"
286                "layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
287                "layout(location = 1) ${auxqualifier} ${qualifier}        in float in_data_${qualifier};\n"
288                "layout(location = 0) out vec4 out_color;\n"
289                "layout (binding = 0, std140) writeonly buffer Output {\n"
290                "    vec4 values [${numValues}];\n"
291                "} sb_out;\n"
292                "\n"
293                "void main()\n"
294                "{\n"
295                "    uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + "
296                "gl_SampleID;\n"
297                "    // Barycentric coodinates (I, J, K)\n"
298                "    vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
299                "\n"
300                "    // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
301                "    float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
302                "    // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
303                "    float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
304                "    // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
305                "    float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
306                "    // Match data component with barycentric coordinate\n"
307                "    vec3  data  = vec3(data1, data2, data0);\n"
308                "\n"
309                "    float res      = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
310                "    float expected = in_data_${qualifier};\n"
311                "\n"
312                "    sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
313                "\n"
314                "    const float threshold = 0.0005f;\n"
315                "    if (abs(res - expected) < threshold)\n"
316                "        out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
317                "    else\n"
318                "        out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
319                "}\n"));
320 
321     map<string, string> attributes;
322     attributes["width"]        = de::toString(WIDTH);
323     attributes["numValues"]    = de::toString(numValues * m_data.samples);
324     attributes["qualifier"]    = interpolationToString(m_data.interpolation);
325     attributes["auxqualifier"] = auxiliaryQualifierToString(m_data.auxiliaryStorage);
326     attributes["barycoord"]    = barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
327     attributes["samples"]      = de::toString(m_data.samples);
328 
329     programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
330     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
331 }
332 
createInstance(Context & context) const333 TestInstance *DrawTestCase::createInstance(Context &context) const
334 {
335     return new DrawTestInstance(context, m_data);
336 }
337 
iterate(void)338 tcu::TestStatus DrawTestInstance::iterate(void)
339 {
340     de::SharedPtr<Image> colorTargetImage;
341     de::SharedPtr<Image> multisampleTargetImage;
342     tcu::TestLog &log = m_context.getTestContext().getLog();
343 
344     // Run two iterations with shaders that have different interpolation decorations. Images should still match.
345     const DeviceInterface &vk = m_context.getDeviceInterface();
346     const VkDevice device     = m_context.getDevice();
347     const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex());
348     Move<VkCommandPool> cmdPool     = createCommandPool(vk, device, &cmdPoolCreateInfo);
349     Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
350     Move<VkCommandBuffer> secCmdBuffer;
351     const Unique<VkShaderModule> vs(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
352     const Unique<VkShaderModule> fs(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
353     de::SharedPtr<Buffer> vertexBuffer;
354     de::SharedPtr<Buffer> ssboBuffer;
355 
356     vk::VkFormat imageFormat    = VK_FORMAT_R8G8B8A8_UNORM;
357     const uint32_t numValues    = WIDTH * HEIGHT * m_data.samples;
358     const bool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
359 
360     // Create color buffer images.
361     {
362         const VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
363         const ImageCreateInfo targetImageCreateInfo(
364             VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
365             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
366         colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(),
367                                                  m_context.getUniversalQueueFamilyIndex());
368 
369         if (useMultisampling)
370         {
371             const ImageCreateInfo multisampleTargetImageCreateInfo(
372                 VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples, VK_IMAGE_TILING_OPTIMAL,
373                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
374                     VK_IMAGE_USAGE_TRANSFER_DST_BIT);
375             multisampleTargetImage =
376                 Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(),
377                                       m_context.getUniversalQueueFamilyIndex());
378         }
379     }
380 
381     const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
382     m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
383 
384     if (useMultisampling)
385     {
386         const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleTargetImage->object(),
387                                                               vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat);
388         m_multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
389     }
390 
391     // Create render pass
392     if (!m_data.groupParams->useDynamicRendering)
393     {
394         RenderPassCreateInfo renderPassCreateInfo;
395         renderPassCreateInfo.addAttachment(
396             AttachmentDescription(imageFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
397                                   VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
398                                   VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL));
399 
400         const VkAttachmentReference colorAttachmentRef       = {0u, VK_IMAGE_LAYOUT_GENERAL};
401         const VkAttachmentReference multisampleAttachmentRef = {1u, VK_IMAGE_LAYOUT_GENERAL};
402 
403         if (useMultisampling)
404         {
405             renderPassCreateInfo.addAttachment(AttachmentDescription(
406                 imageFormat, m_data.samples, vk::VK_ATTACHMENT_LOAD_OP_CLEAR, vk::VK_ATTACHMENT_STORE_OP_STORE,
407                 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
408                 vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL));
409         }
410 
411         renderPassCreateInfo.addSubpass(
412             SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1u,
413                                useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
414                                useMultisampling ? &colorAttachmentRef : DE_NULL, AttachmentReference(), 0, DE_NULL));
415 
416         m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
417 
418         // Create framebuffer
419         vector<VkImageView> colorAttachments{*m_colorTargetView};
420         if (useMultisampling)
421             colorAttachments.push_back(*m_multisampleTargetView);
422 
423         const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
424         m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
425     }
426 
427     // Create vertex buffer.
428     {
429         const PositionValueVertex vertices[] = {
430             PositionValueVertex(tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), // Coord
431                                 float(1.0f)),                       // Value
432 
433             PositionValueVertex(tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f), // Coord
434                                 float(0.0f)),                          // Value
435             PositionValueVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 2.0f),     // Coord
436                                 float(0.5f)),                          // Value
437             PositionValueVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 0.5f),    // Coord
438                                 float(1.0f)),                          // Value
439         };
440 
441         const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
442         vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
443                                               m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
444         uint8_t *ptr = reinterpret_cast<uint8_t *>(vertexBuffer->getBoundMemory().getHostPtr());
445 
446         deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
447         flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(),
448                                vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
449     }
450 
451     // Create SSBO buffer
452     {
453         const VkDeviceSize dataSize = sizeof(tcu::Vec4) * numValues;
454         ssboBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
455                                             m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
456         uint8_t *ptr = reinterpret_cast<uint8_t *>(ssboBuffer->getBoundMemory().getHostPtr());
457 
458         deMemset(ptr, 0, static_cast<size_t>(dataSize));
459         flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(),
460                                ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
461     }
462 
463     // Create Descriptor Set layout
464     {
465         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
466                                     .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
467                                     .build(vk, device);
468     }
469 
470     // Create Descriptor Set
471     {
472         m_descriptorPool = DescriptorPoolBuilder()
473                                .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
474                                .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
475 
476         m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
477 
478         const VkDescriptorBufferInfo bufferInfo = {
479             ssboBuffer->object(), // VkBuffer buffer;
480             0u,                   // VkDeviceSize offset;
481             VK_WHOLE_SIZE         // VkDeviceSize range;
482         };
483 
484         DescriptorSetUpdateBuilder()
485             .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
486                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
487             .update(vk, device);
488     }
489 
490     // Create pipeline
491     {
492         const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
493 
494         VkViewport viewport = makeViewport(WIDTH, HEIGHT);
495         VkRect2D scissor    = makeRect2D(WIDTH, HEIGHT);
496 
497         const VkVertexInputBindingDescription vertexInputBindingDescription = {
498             0, (uint32_t)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX};
499 
500         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
501             {0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
502             {1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (uint32_t)(sizeof(float) * 4)}};
503 
504         PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(
505             1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
506 
507         m_pipelineLayout = makePipelineLayout(vk, device, *m_descriptorSetLayout);
508 
509         PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
510         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
511         pipelineCreateInfo.addShader(
512             PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
513         pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
514         pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
515         pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
516         pipelineCreateInfo.addState(
517             PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
518         pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
519         pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
520         pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
521 
522 #ifndef CTS_USES_VULKANSC
523         VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
524                                                              DE_NULL,
525                                                              0u,
526                                                              1u,
527                                                              &imageFormat,
528                                                              VK_FORMAT_UNDEFINED,
529                                                              VK_FORMAT_UNDEFINED};
530 
531         if (m_data.groupParams->useDynamicRendering)
532             pipelineCreateInfo.pNext = &renderingCreateInfo;
533 #endif // CTS_USES_VULKANSC
534 
535         m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
536     }
537 
538     // Queue draw and read results.
539     {
540         const VkQueue queue = m_context.getUniversalQueue();
541         const ImageSubresourceRange subresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
542         const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
543         const VkRect2D renderArea  = makeRect2D(WIDTH, HEIGHT);
544         const VkBuffer buffer      = vertexBuffer->object();
545 
546         vector<VkClearValue> clearColors;
547         clearColors.push_back(makeClearValueColor(clearColor));
548         if (useMultisampling)
549             clearColors.push_back(makeClearValueColor(clearColor));
550 
551 #ifndef CTS_USES_VULKANSC
552         if (m_data.groupParams->useSecondaryCmdBuffer)
553         {
554             secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
555 
556             // record secondary command buffer
557             if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
558             {
559                 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat,
560                                         VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
561                 beginDynamicRender(*secCmdBuffer, renderArea, clearColors.data());
562             }
563             else
564                 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat);
565 
566             drawCommands(*secCmdBuffer, buffer);
567 
568             if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
569                 endRendering(vk, *secCmdBuffer);
570 
571             endCommandBuffer(vk, *secCmdBuffer);
572 
573             // record primary command buffer
574             beginCommandBuffer(vk, *cmdBuffer, 0u);
575 
576             if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
577                 beginDynamicRender(*cmdBuffer, renderArea, clearColors.data(),
578                                    VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
579 
580             vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
581 
582             if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
583                 endRendering(vk, *cmdBuffer);
584 
585             endCommandBuffer(vk, *cmdBuffer);
586         }
587         else if (m_data.groupParams->useDynamicRendering)
588         {
589             beginCommandBuffer(vk, *cmdBuffer);
590             beginDynamicRender(*cmdBuffer, renderArea, clearColors.data());
591             drawCommands(*cmdBuffer, buffer);
592             endRendering(vk, *cmdBuffer);
593             endCommandBuffer(vk, *cmdBuffer);
594         }
595 #endif // CTS_USES_VULKANSC
596 
597         if (!m_data.groupParams->useDynamicRendering)
598         {
599             beginCommandBuffer(vk, *cmdBuffer);
600             beginRenderPass(*cmdBuffer, renderArea, clearColors.data(), (uint32_t)clearColors.size());
601             drawCommands(*cmdBuffer, buffer);
602             endRenderPass(vk, *cmdBuffer);
603             endCommandBuffer(vk, *cmdBuffer);
604         }
605 
606         submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
607     }
608 
609     qpTestResult res = QP_TEST_RESULT_PASS;
610 
611     {
612         const Allocation &resultAlloc = ssboBuffer->getBoundMemory();
613         invalidateAlloc(vk, device, resultAlloc);
614 
615         const tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4 *>(resultAlloc.getHostPtr());
616         for (uint32_t valueNdx = 0u; valueNdx < numValues; valueNdx++)
617         {
618             if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
619             {
620                 log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got "
621                     << ptr[valueNdx].y() << tcu::TestLog::EndMessage;
622                 res = QP_TEST_RESULT_FAIL;
623             }
624         }
625     }
626 
627     return tcu::TestStatus(res, qpGetTestResultName(res));
628 }
629 
beginRenderPass(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,uint32_t clearValueCount) const630 void DrawTestInstance::beginRenderPass(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue *pClearValues,
631                                        uint32_t clearValueCount) const
632 {
633     const DeviceInterface &vk = m_context.getDeviceInterface();
634 
635     const VkRenderPassBeginInfo renderPassBeginInfo{
636         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
637         DE_NULL,                                  // const void* pNext;
638         *m_renderPass,                            // VkRenderPass renderPass;
639         *m_framebuffer,                           // VkFramebuffer framebuffer;
640         renderArea,                               // VkRect2D renderArea;
641         clearValueCount,                          // uint32_t clearValueCount;
642         pClearValues,                             // const VkClearValue* pClearValues;
643     };
644 
645     vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
646 }
647 
drawCommands(VkCommandBuffer cmdBuffer,VkBuffer vertexBuffer) const648 void DrawTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const
649 {
650     const DeviceInterface &vk             = m_context.getDeviceInterface();
651     const VkDeviceSize vertexBufferOffset = 0;
652 
653     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
654     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
655     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet,
656                              0u, DE_NULL);
657     vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
658 }
659 
660 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags) const661 void DrawTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
662                                                VkRenderingFlagsKHR renderingFlags) const
663 {
664     VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
665         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
666         DE_NULL,                                                         // const void* pNext;
667         renderingFlags,                                                  // VkRenderingFlagsKHR flags;
668         0u,                                                              // uint32_t viewMask;
669         1u,                                                              // uint32_t colorAttachmentCount;
670         &colorFormat,                                                    // const VkFormat* pColorAttachmentFormats;
671         VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
672         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
673         m_data.samples,                                                  // VkSampleCountFlagBits rasterizationSamples;
674     };
675     const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
676 
677     VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
678     if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
679         usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
680 
681     const VkCommandBufferBeginInfo commandBufBeginParams{
682         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
683         DE_NULL,                                     // const void* pNext;
684         usageFlags,                                  // VkCommandBufferUsageFlags flags;
685         &bufferInheritanceInfo};
686 
687     const DeviceInterface &vk = m_context.getDeviceInterface();
688     VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
689 }
690 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,VkRenderingFlagsKHR renderingFlags) const691 void DrawTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
692                                           const VkClearValue *pClearValues, VkRenderingFlagsKHR renderingFlags) const
693 {
694     const DeviceInterface &vk   = m_context.getDeviceInterface();
695     const bool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
696 
697     VkRenderingAttachmentInfoKHR colorAttachment{
698         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,                       // VkStructureType sType;
699         DE_NULL,                                                               // const void* pNext;
700         useMultisampling ? *m_multisampleTargetView : *m_colorTargetView,      // VkImageView imageView;
701         VK_IMAGE_LAYOUT_GENERAL,                                               // VkImageLayout imageLayout;
702         useMultisampling ? VK_RESOLVE_MODE_AVERAGE_BIT : VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
703         useMultisampling ? *m_colorTargetView : DE_NULL,                       // VkImageView resolveImageView;
704         VK_IMAGE_LAYOUT_GENERAL,                                               // VkImageLayout resolveImageLayout;
705         useMultisampling ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
706         VK_ATTACHMENT_STORE_OP_STORE,                                                // VkAttachmentStoreOp storeOp;
707         pClearValues[0]                                                              // VkClearValue clearValue;
708     };
709 
710     VkRenderingInfoKHR renderingInfo{
711         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
712         DE_NULL,
713         renderingFlags,   // VkRenderingFlagsKHR flags;
714         renderArea,       // VkRect2D renderArea;
715         1u,               // uint32_t layerCount;
716         0u,               // uint32_t viewMask;
717         1u,               // uint32_t colorAttachmentCount;
718         &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
719         DE_NULL,          // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
720         DE_NULL,          // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
721     };
722 
723     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
724 }
725 #endif // CTS_USES_VULKANSC
726 
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)727 void createTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
728 {
729     tcu::TestContext &testCtx = testGroup->getTestContext();
730 
731     const VkSampleCountFlagBits samples[] = {
732         VK_SAMPLE_COUNT_1_BIT,  VK_SAMPLE_COUNT_2_BIT,  VK_SAMPLE_COUNT_4_BIT,  VK_SAMPLE_COUNT_8_BIT,
733         VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_64_BIT,
734     };
735 
736     const Interpolation interTypes[] = {SMOOTH, NOPERSPECTIVE};
737 
738     const AuxiliaryQualifier auxQualifiers[] = {
739         AUX_NONE,
740         AUX_SAMPLE,
741         AUX_CENTROID,
742     };
743 
744     for (uint32_t sampleNdx = 0; sampleNdx < DE_LENGTH_OF_ARRAY(samples); sampleNdx++)
745     {
746         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
747         if (groupParams->useSecondaryCmdBuffer && (sampleNdx > VK_SAMPLE_COUNT_2_BIT))
748             continue;
749 
750         for (uint32_t auxNdx = 0; auxNdx < DE_LENGTH_OF_ARRAY(auxQualifiers); auxNdx++)
751             for (uint32_t interNdx = 0; interNdx < DE_LENGTH_OF_ARRAY(interTypes); interNdx++)
752             {
753                 if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
754                     continue;
755 
756                 const DrawParams params{interTypes[interNdx], samples[sampleNdx], auxQualifiers[auxNdx], groupParams};
757                 testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), params));
758             }
759     }
760 }
761 
762 } // namespace
763 
createExplicitVertexParameterTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)764 tcu::TestCaseGroup *createExplicitVertexParameterTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
765 {
766     // Tests for VK_AMD_shader_explicit_vertex_parameter.
767     return createTestGroup(testCtx, "explicit_vertex_parameter", createTests, groupParams);
768 }
769 
770 } // namespace Draw
771 } // namespace vkt
772