xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/draw/vktDrawInstancedTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Instanced Draw Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawInstancedTests.hpp"
26 
27 #include <climits>
28 
29 #include "deSharedPtr.hpp"
30 #include "rrRenderer.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuRGBA.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vktDrawBufferObjectUtil.hpp"
40 #include "vktDrawCreateInfoUtil.hpp"
41 #include "vktDrawImageObjectUtil.hpp"
42 #include "vktDrawTestCaseUtil.hpp"
43 
44 namespace vkt
45 {
46 namespace Draw
47 {
48 namespace
49 {
50 
51 static const int QUAD_GRID_SIZE = 8;
52 static const int WIDTH          = 128;
53 static const int HEIGHT         = 128;
54 
55 enum AttributeDivisor
56 {
57     ATTRIBUTE_DIVISOR_NONE,
58     ATTRIBUTE_DIVISOR_EXT,
59     ATTRIBUTE_DIVISOR_KHR,
60 };
61 
62 struct TestParams
63 {
64     enum DrawFunction
65     {
66         FUNCTION_DRAW = 0,
67         FUNCTION_DRAW_INDEXED,
68         FUNCTION_DRAW_INDIRECT,
69         FUNCTION_DRAW_INDEXED_INDIRECT,
70 
71         FUNTION_LAST
72     };
73 
74     DrawFunction function;
75     vk::VkPrimitiveTopology topology;
76     const SharedGroupParams groupParams;
77 
78     AttributeDivisor testAttribDivisor;
79     uint32_t attribDivisor;
80 
81     bool testMultiview;
82 
83     bool dynamicState;
84 
85     bool useMaintenance5Ext;
86 
isIndirectDrawvkt::Draw::__anon5dadb2610111::TestParams87     bool isIndirectDraw(void) const
88     {
89         return (function == FUNCTION_DRAW_INDIRECT || function == FUNCTION_DRAW_INDEXED_INDIRECT);
90     }
91 };
92 
93 struct VertexPositionAndColor
94 {
VertexPositionAndColorvkt::Draw::__anon5dadb2610111::VertexPositionAndColor95     VertexPositionAndColor(tcu::Vec4 position_, tcu::Vec4 color_) : position(position_), color(color_)
96     {
97     }
98 
99     tcu::Vec4 position;
100     tcu::Vec4 color;
101 };
102 
operator <<(std::ostream & str,TestParams const & v)103 std::ostream &operator<<(std::ostream &str, TestParams const &v)
104 {
105     std::ostringstream string;
106 
107     if (v.dynamicState)
108         string << "dynamic_state_";
109 
110     switch (v.function)
111     {
112     case TestParams::FUNCTION_DRAW:
113         string << "draw";
114         break;
115     case TestParams::FUNCTION_DRAW_INDEXED:
116         string << "draw_indexed";
117         break;
118     case TestParams::FUNCTION_DRAW_INDIRECT:
119         string << "draw_indirect";
120         break;
121     case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
122         string << "draw_indexed_indirect";
123         break;
124     default:
125         DE_ASSERT(false);
126     }
127 
128     string << "_" << de::toString(v.topology);
129 
130     if (v.testAttribDivisor == ATTRIBUTE_DIVISOR_EXT)
131         string << "_attrib_divisor_" << v.attribDivisor;
132     else if (v.testAttribDivisor == ATTRIBUTE_DIVISOR_KHR)
133         string << "_khr_attrib_divisor_" << v.attribDivisor;
134 
135     if (v.testMultiview)
136         string << "_multiview";
137 
138     return str << string.str();
139 }
140 
mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)141 rr::PrimitiveType mapVkPrimitiveTopology(vk::VkPrimitiveTopology primitiveTopology)
142 {
143     switch (primitiveTopology)
144     {
145     case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
146         return rr::PRIMITIVETYPE_POINTS;
147     case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
148         return rr::PRIMITIVETYPE_LINES;
149     case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
150         return rr::PRIMITIVETYPE_LINE_STRIP;
151     case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
152         return rr::PRIMITIVETYPE_TRIANGLES;
153     case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
154         return rr::PRIMITIVETYPE_TRIANGLE_FAN;
155     case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
156         return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
157     case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
158         return rr::PRIMITIVETYPE_LINES_ADJACENCY;
159     case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
160         return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
161     case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
162         return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
163     case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
164         return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
165     default:
166         DE_ASSERT(false);
167     }
168     return rr::PRIMITIVETYPE_LAST;
169 }
170 
171 template <typename T>
createAndUploadBuffer(const std::vector<T> data,const vk::DeviceInterface & vk,const Context & context,vk::VkBufferUsageFlags usage)172 de::SharedPtr<Buffer> createAndUploadBuffer(const std::vector<T> data, const vk::DeviceInterface &vk,
173                                             const Context &context, vk::VkBufferUsageFlags usage)
174 {
175     const vk::VkDeviceSize dataSize = data.size() * sizeof(T);
176     de::SharedPtr<Buffer> buffer =
177         Buffer::createAndAlloc(vk, context.getDevice(), BufferCreateInfo(dataSize, usage),
178                                context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
179 
180     uint8_t *ptr = reinterpret_cast<uint8_t *>(buffer->getBoundMemory().getHostPtr());
181 
182     deMemcpy(ptr, &data[0], static_cast<size_t>(dataSize));
183 
184     vk::flushAlloc(vk, context.getDevice(), buffer->getBoundMemory());
185     return buffer;
186 }
187 
188 class TestVertShader : public rr::VertexShader
189 {
190 public:
TestVertShader(int numInstances,int firstInstance)191     TestVertShader(int numInstances, int firstInstance)
192         : rr::VertexShader(3, 1)
193         , m_numInstances(numInstances)
194         , m_firstInstance(firstInstance)
195     {
196         m_inputs[0].type  = rr::GENERICVECTYPE_FLOAT;
197         m_inputs[1].type  = rr::GENERICVECTYPE_FLOAT;
198         m_inputs[2].type  = rr::GENERICVECTYPE_FLOAT;
199         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
200     }
201 
~TestVertShader()202     virtual ~TestVertShader()
203     {
204     }
205 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const206     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
207     {
208         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
209         {
210             const int instanceNdx    = packets[packetNdx]->instanceNdx + m_firstInstance;
211             const tcu::Vec4 position = rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx,
212                                                                  packets[packetNdx]->vertexNdx, m_firstInstance);
213             const tcu::Vec4 color    = rr::readVertexAttribFloat(inputs[1], packets[packetNdx]->instanceNdx,
214                                                                  packets[packetNdx]->vertexNdx, m_firstInstance);
215             const tcu::Vec4 color2   = rr::readVertexAttribFloat(inputs[2], packets[packetNdx]->instanceNdx,
216                                                                  packets[packetNdx]->vertexNdx, m_firstInstance);
217             packets[packetNdx]->position =
218                 position + tcu::Vec4((float)(packets[packetNdx]->instanceNdx * 2.0 / m_numInstances), 0.0, 0.0, 0.0);
219             packets[packetNdx]->outputs[0] =
220                 color + tcu::Vec4((float)instanceNdx / (float)m_numInstances, 0.0, 0.0, 1.0) + color2;
221         }
222     }
223 
224 private:
225     const int m_numInstances;
226     const int m_firstInstance;
227 };
228 
229 class TestFragShader : public rr::FragmentShader
230 {
231 public:
TestFragShader(void)232     TestFragShader(void) : rr::FragmentShader(1, 1)
233     {
234         m_inputs[0].type  = rr::GENERICVECTYPE_FLOAT;
235         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
236     }
237 
~TestFragShader()238     virtual ~TestFragShader()
239     {
240     }
241 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const242     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
243                         const rr::FragmentShadingContext &context) const
244     {
245         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
246         {
247             rr::FragmentPacket &packet = packets[packetNdx];
248             for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
249             {
250                 const tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
251                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
252             }
253         }
254     }
255 };
256 
257 class InstancedDrawInstance : public TestInstance
258 {
259 public:
260     InstancedDrawInstance(Context &context, TestParams params);
261     virtual tcu::TestStatus iterate(void);
262 
263 private:
264     void prepareVertexData(int instanceCount, int firstInstance, int instanceDivisor);
265     void preRenderCommands(const vk::VkClearValue &clearColor, uint32_t numLayers);
266     void draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer vertexBuffer, vk::VkBuffer instancedVertexBuffer,
267               de::SharedPtr<Buffer> indexBuffer, de::SharedPtr<Buffer> indirectBuffer, vk::VkDeviceSize indexBufferSize,
268               uint32_t firstInstance, uint32_t instanceCount);
269     void cmdBindIndexBufferImpl(vk::VkCommandBuffer commandBuffer, vk::VkBuffer indexBuffer, vk::VkDeviceSize offset,
270                                 vk::VkDeviceSize size, vk::VkIndexType indexType);
271 
272 #ifndef CTS_USES_VULKANSC
273     void beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags = 0u);
274 #endif // CTS_USES_VULKANSC
275 
276 private:
277     const TestParams m_params;
278     const vk::DeviceInterface &m_vk;
279 
280     vk::VkFormat m_colorAttachmentFormat;
281 
282     vk::Move<vk::VkPipeline> m_pipeline;
283     vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
284 
285     de::SharedPtr<Image> m_colorTargetImage;
286     vk::Move<vk::VkImageView> m_colorTargetView;
287 
288     PipelineCreateInfo::VertexInputState m_vertexInputState;
289 
290     vk::Move<vk::VkCommandPool> m_cmdPool;
291     vk::Move<vk::VkCommandBuffer> m_cmdBuffer;
292     vk::Move<vk::VkCommandBuffer> m_secCmdBuffer;
293 
294     vk::Move<vk::VkFramebuffer> m_framebuffer;
295     vk::Move<vk::VkRenderPass> m_renderPass;
296 
297     // Vertex data
298     std::vector<VertexPositionAndColor> m_data;
299     std::vector<uint32_t> m_indexes;
300     std::vector<tcu::Vec4> m_instancedColor;
301 };
302 
303 class InstancedDrawCase : public TestCase
304 {
305 public:
InstancedDrawCase(tcu::TestContext & testCtx,const std::string & name,TestParams params)306     InstancedDrawCase(tcu::TestContext &testCtx, const std::string &name, TestParams params)
307         : TestCase(testCtx, name)
308         , m_params(params)
309     {
310         m_vertexShader = "#version 430\n"
311                          "layout(location = 0) in vec4 in_position;\n"
312                          "layout(location = 1) in vec4 in_color;\n"
313                          "layout(location = 2) in vec4 in_color_2;\n"
314                          "layout(push_constant) uniform TestParams {\n"
315                          "    float firstInstance;\n"
316                          "    float instanceCount;\n"
317                          "} params;\n"
318                          "layout(location = 0) out vec4 out_color;\n"
319                          "out gl_PerVertex {\n"
320                          "    vec4  gl_Position;\n"
321                          "    float gl_PointSize;\n"
322                          "};\n"
323                          "void main() {\n"
324                          "    gl_PointSize = 1.0;\n"
325                          "    gl_Position  = in_position + vec4(float(gl_InstanceIndex - params.firstInstance) * 2.0 / "
326                          "params.instanceCount, 0.0, 0.0, 0.0);\n"
327                          "    out_color    = in_color + vec4(float(gl_InstanceIndex) / params.instanceCount, 0.0, 0.0, "
328                          "1.0) + in_color_2;\n"
329                          "}\n";
330 
331         m_fragmentShader = "#version 430\n"
332                            "layout(location = 0) in vec4 in_color;\n"
333                            "layout(location = 0) out vec4 out_color;\n"
334                            "void main()\n"
335                            "{\n"
336                            "    out_color = in_color;\n"
337                            "}\n";
338     }
339 
checkSupport(Context & context) const340     virtual void checkSupport(Context &context) const
341     {
342         if (m_params.dynamicState)
343         {
344             const auto physicalVertexInputDynamicState = context.getVertexInputDynamicStateFeaturesEXT();
345             if (!physicalVertexInputDynamicState.vertexInputDynamicState)
346                 TCU_THROW(NotSupportedError, "Implementation does not support vertexInputDynamicState");
347         }
348         if (m_params.testAttribDivisor == ATTRIBUTE_DIVISOR_EXT)
349         {
350             context.requireDeviceFunctionality("VK_EXT_vertex_attribute_divisor");
351 
352             const auto &vertexAttributeDivisorFeatures = context.getVertexAttributeDivisorFeatures();
353             if (m_params.attribDivisor != 1 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
354                 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisor");
355 
356             if (m_params.attribDivisor == 0 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateZeroDivisor)
357                 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisorZero");
358         }
359 #ifndef CTS_USES_VULKANSC
360         else if (m_params.testAttribDivisor == ATTRIBUTE_DIVISOR_KHR)
361         {
362             context.requireDeviceFunctionality("VK_KHR_vertex_attribute_divisor");
363 
364             const vk::VkPhysicalDeviceVertexAttributeDivisorFeaturesKHR &vertexAttributeDivisorFeatures =
365                 context.getVertexAttributeDivisorFeatures();
366 
367             if (m_params.attribDivisor != 1 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
368                 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisor");
369 
370             if (m_params.attribDivisor == 0 && !vertexAttributeDivisorFeatures.vertexAttributeInstanceRateZeroDivisor)
371                 TCU_THROW(NotSupportedError, "Implementation does not support vertexAttributeInstanceRateDivisorZero");
372 
373             const vk::VkPhysicalDeviceVertexAttributeDivisorPropertiesKHR &vertexAttributeDivisorProperties =
374                 context.getVertexAttributeDivisorProperties();
375 
376             if (!vertexAttributeDivisorProperties.supportsNonZeroFirstInstance)
377                 TCU_THROW(NotSupportedError, "Implementation does not support supportsNonZeroFirstInstance");
378         }
379 #endif
380 
381         if (m_params.testMultiview)
382         {
383             context.requireDeviceFunctionality("VK_KHR_multiview");
384 
385             const vk::VkPhysicalDeviceMultiviewFeatures &multiviewFeatures = context.getMultiviewFeatures();
386 
387             if (!multiviewFeatures.multiview)
388                 TCU_THROW(NotSupportedError, "Implementation does not support multiview feature");
389         }
390 
391 #ifndef CTS_USES_VULKANSC
392         if (m_params.groupParams->useDynamicRendering)
393             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
394 
395         if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
396             context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
397             !context.getPortabilitySubsetFeatures().triangleFans)
398         {
399             TCU_THROW(NotSupportedError,
400                       "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
401         }
402 
403         if (m_params.useMaintenance5Ext)
404         {
405             context.requireDeviceFunctionality(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
406         }
407 #endif // CTS_USES_VULKANSC
408     }
409 
createInstance(Context & context) const410     TestInstance *createInstance(Context &context) const
411     {
412         return new InstancedDrawInstance(context, m_params);
413     }
414 
initPrograms(vk::SourceCollections & programCollection) const415     virtual void initPrograms(vk::SourceCollections &programCollection) const
416     {
417         programCollection.glslSources.add("InstancedDrawVert") << glu::VertexSource(m_vertexShader);
418         programCollection.glslSources.add("InstancedDrawFrag") << glu::FragmentSource(m_fragmentShader);
419     }
420 
421 private:
422     const TestParams m_params;
423     std::string m_vertexShader;
424     std::string m_fragmentShader;
425 };
426 
InstancedDrawInstance(Context & context,TestParams params)427 InstancedDrawInstance::InstancedDrawInstance(Context &context, TestParams params)
428     : TestInstance(context)
429     , m_params(params)
430     , m_vk(context.getDeviceInterface())
431     , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
432 {
433     const vk::VkDevice device       = m_context.getDevice();
434     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
435 
436     const vk::VkPushConstantRange pushConstantRange = {
437         vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlags    stageFlags;
438         0u,                             // uint32_t              offset;
439         (uint32_t)sizeof(float) * 2,    // uint32_t              size;
440     };
441 
442     const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0, DE_NULL, 1, &pushConstantRange);
443     m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
444 
445     uint32_t arrayLayers                   = m_params.testMultiview ? 2 : 1;
446     const vk::VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
447     const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1,
448                                                 arrayLayers, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
449                                                 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
450                                                     vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
451                                                     vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
452 
453     m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(),
454                                                m_context.getUniversalQueueFamilyIndex());
455 
456     const enum vk::VkImageViewType imageViewType =
457         m_params.testMultiview ? vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY : vk::VK_IMAGE_VIEW_TYPE_2D;
458     ImageSubresourceRange subresourceRange = ImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
459 
460     if (m_params.testMultiview)
461         subresourceRange.layerCount = 2;
462 
463     const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), imageViewType, m_colorAttachmentFormat,
464                                                   subresourceRange);
465     m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
466 
467     if (!m_params.groupParams->useDynamicRendering)
468     {
469         RenderPassCreateInfo renderPassCreateInfo;
470         renderPassCreateInfo.addAttachment(AttachmentDescription(
471             m_colorAttachmentFormat, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
472             vk::VK_ATTACHMENT_STORE_OP_STORE, vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_STORE,
473             vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL));
474 
475         const vk::VkAttachmentReference colorAttachmentReference = {0, vk::VK_IMAGE_LAYOUT_GENERAL};
476 
477         renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1,
478                                                            &colorAttachmentReference, DE_NULL, AttachmentReference(), 0,
479                                                            DE_NULL));
480 
481         vk::VkRenderPassMultiviewCreateInfo renderPassMultiviewCreateInfo;
482         // Bit mask that specifies which view rendering is broadcast to
483         // 0011 = Broadcast to first and second view (layer)
484         const uint32_t viewMask = 0x3;
485         // Bit mask that specifices correlation between views
486         // An implementation may use this for optimizations (concurrent render)
487         const uint32_t correlationMask = 0x3;
488 
489         if (m_params.testMultiview)
490         {
491             DE_ASSERT(renderPassCreateInfo.subpassCount == 1);
492 
493             renderPassMultiviewCreateInfo.sType        = vk::VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
494             renderPassMultiviewCreateInfo.pNext        = DE_NULL;
495             renderPassMultiviewCreateInfo.subpassCount = renderPassCreateInfo.subpassCount;
496             renderPassMultiviewCreateInfo.pViewMasks   = &viewMask;
497             renderPassMultiviewCreateInfo.correlationMaskCount = 1u;
498             renderPassMultiviewCreateInfo.pCorrelationMasks    = &correlationMask;
499             renderPassMultiviewCreateInfo.pViewOffsets         = DE_NULL;
500             renderPassMultiviewCreateInfo.dependencyCount      = 0u;
501 
502             renderPassCreateInfo.pNext = &renderPassMultiviewCreateInfo;
503         }
504 
505         m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
506 
507         // create framebuffer
508         std::vector<vk::VkImageView> colorAttachments{*m_colorTargetView};
509         const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
510         m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
511     }
512 
513     const vk::VkVertexInputBindingDescription vertexInputBindingDescription[2] = {
514         {
515             0u,
516             (uint32_t)sizeof(VertexPositionAndColor),
517             vk::VK_VERTEX_INPUT_RATE_VERTEX,
518         },
519         {
520             1u,
521             (uint32_t)sizeof(tcu::Vec4),
522             vk::VK_VERTEX_INPUT_RATE_INSTANCE,
523         },
524     };
525 
526     const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
527         {0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
528         {
529             1u,
530             0u,
531             vk::VK_FORMAT_R32G32B32A32_SFLOAT,
532             (uint32_t)sizeof(tcu::Vec4),
533         },
534         {
535             2u,
536             1u,
537             vk::VK_FORMAT_R32G32B32A32_SFLOAT,
538             0,
539         }};
540 
541     m_vertexInputState = PipelineCreateInfo::VertexInputState(2, vertexInputBindingDescription,
542                                                               DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),
543                                                               vertexInputAttributeDescriptions);
544 
545     const vk::VkVertexInputBindingDivisorDescriptionEXT vertexInputBindingDivisorDescription = {
546         1u,
547         m_params.attribDivisor,
548     };
549 
550     if (m_params.testAttribDivisor != ATTRIBUTE_DIVISOR_NONE)
551         m_vertexInputState.addDivisors(1, &vertexInputBindingDivisorDescription);
552 
553     const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
554     m_cmdPool   = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
555     m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
556     if (m_params.groupParams->useSecondaryCmdBuffer)
557         m_secCmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY);
558 
559     const vk::Unique<vk::VkShaderModule> vs(
560         createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawVert"), 0));
561     const vk::Unique<vk::VkShaderModule> fs(
562         createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawFrag"), 0));
563 
564     const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
565 
566     vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT);
567     vk::VkRect2D scissor    = vk::makeRect2D(WIDTH, HEIGHT);
568 
569     PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
570     pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
571     pipelineCreateInfo.addShader(
572         PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
573     pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_params.topology));
574     pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
575     pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport),
576                                                                   std::vector<vk::VkRect2D>(1, scissor)));
577     pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
578     pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
579     pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
580 
581     if (m_params.dynamicState)
582     {
583         vk::VkDynamicState dynStates[] = {vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT};
584 
585         vk::VkPipelineDynamicStateCreateInfo dynamicState{vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
586                                                           DE_NULL, 0, 1, dynStates};
587         pipelineCreateInfo.addState(dynamicState);
588     }
589     else
590     {
591         pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
592     }
593 
594 #ifndef CTS_USES_VULKANSC
595     vk::VkPipelineRenderingCreateInfoKHR renderingFormatCreateInfo{
596         vk::VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
597         DE_NULL,
598         0u,
599         1u,
600         &m_colorAttachmentFormat,
601         vk::VK_FORMAT_UNDEFINED,
602         vk::VK_FORMAT_UNDEFINED};
603 
604     if (m_params.groupParams->useDynamicRendering)
605     {
606         pipelineCreateInfo.pNext = &renderingFormatCreateInfo;
607 
608         if (m_params.testMultiview)
609             renderingFormatCreateInfo.viewMask = 3u;
610     }
611 #endif // CTS_USES_VULKANSC
612 
613     m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
614 }
615 
iterate()616 tcu::TestStatus InstancedDrawInstance::iterate()
617 {
618     const vk::VkQueue queue                      = m_context.getUniversalQueue();
619     const vk::VkDevice device                    = m_context.getDevice();
620     static const uint32_t instanceCounts[]       = {0, 1, 2, 4, 20};
621     static const uint32_t firstInstanceIndices[] = {0, 1, 3, 4, 20};
622     const uint32_t numLayers                     = m_params.testMultiview ? 2 : 1;
623     const vk::VkRect2D renderArea                = vk::makeRect2D(WIDTH, HEIGHT);
624 
625     qpTestResult res = QP_TEST_RESULT_PASS;
626 
627     const vk::VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
628     int firstInstanceIndicesCount     = DE_LENGTH_OF_ARRAY(firstInstanceIndices);
629 
630     // Require 'drawIndirectFirstInstance' feature to run non-zero firstInstance indirect draw tests.
631     const auto &deviceFeatures = m_context.getDeviceFeatures();
632     if (m_params.isIndirectDraw() && !deviceFeatures.drawIndirectFirstInstance)
633     {
634         firstInstanceIndicesCount = 1;
635     }
636 
637     for (int instanceCountNdx = 0; instanceCountNdx < DE_LENGTH_OF_ARRAY(instanceCounts); instanceCountNdx++)
638     {
639         const uint32_t instanceCount = instanceCounts[instanceCountNdx];
640         for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
641         {
642             // Prepare vertex data for at least one instance
643             const uint32_t prepareCount  = de::max(instanceCount, 1u);
644             const uint32_t firstInstance = firstInstanceIndices[firstInstanceIndexNdx];
645 
646             prepareVertexData(prepareCount, firstInstance,
647                               (m_params.testAttribDivisor != ATTRIBUTE_DIVISOR_NONE) ? m_params.attribDivisor : 1);
648             const de::SharedPtr<Buffer> vertexBuffer =
649                 createAndUploadBuffer(m_data, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
650             const de::SharedPtr<Buffer> instancedVertexBuffer =
651                 createAndUploadBuffer(m_instancedColor, m_vk, m_context, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
652 
653             de::SharedPtr<Buffer> indexBuffer;
654             if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED ||
655                 m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
656                 indexBuffer = createAndUploadBuffer(m_indexes, m_vk, m_context, vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
657 
658             de::SharedPtr<Buffer> indirectBuffer;
659             if (m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
660             {
661                 std::vector<vk::VkDrawIndirectCommand> drawCommands;
662                 drawCommands.push_back({
663                     (uint32_t)m_data.size(), // uint32_t vertexCount;
664                     instanceCount,           // uint32_t instanceCount;
665                     0u,                      // uint32_t firstVertex;
666                     firstInstance            // uint32_t firstInstance;
667                 });
668                 indirectBuffer =
669                     createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
670             }
671             if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
672             {
673                 std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
674                 drawCommands.push_back({
675                     (uint32_t)m_indexes.size(), // uint32_t indexCount;
676                     instanceCount,              // uint32_t instanceCount;
677                     0u,                         // uint32_t firstIndex;
678                     0,                          // int32_t vertexOffset;
679                     firstInstance               // uint32_t firstInstance;
680                 });
681                 indirectBuffer =
682                     createAndUploadBuffer(drawCommands, m_vk, m_context, vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
683             }
684 
685 #ifndef CTS_USES_VULKANSC
686             const uint32_t layerCount = (m_params.testMultiview) ? 2u : 1u;
687             const uint32_t viewMask   = (m_params.testMultiview) ? 3u : 0u;
688             if (m_params.groupParams->useSecondaryCmdBuffer)
689             {
690                 // record secondary command buffer
691                 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
692                 {
693                     beginSecondaryCmdBuffer(vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
694                     beginRendering(m_vk, *m_secCmdBuffer, *m_colorTargetView, renderArea, clearColor,
695                                    vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount,
696                                    viewMask);
697                 }
698                 else
699                     beginSecondaryCmdBuffer();
700 
701                 draw(*m_secCmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer,
702                      indirectBuffer, (m_indexes.size() * sizeof(uint32_t)), firstInstance, instanceCount);
703 
704                 if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
705                     endRendering(m_vk, *m_secCmdBuffer);
706 
707                 endCommandBuffer(m_vk, *m_secCmdBuffer);
708 
709                 // record primary command buffer
710                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
711 
712                 preRenderCommands(clearColor, numLayers);
713 
714                 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
715                 {
716                     beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor,
717                                    vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD,
718                                    vk::VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR, layerCount, viewMask);
719                 }
720 
721                 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
722 
723                 if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
724                     endRendering(m_vk, *m_cmdBuffer);
725 
726                 endCommandBuffer(m_vk, *m_cmdBuffer);
727             }
728             else if (m_params.groupParams->useDynamicRendering)
729             {
730                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
731                 preRenderCommands(clearColor, numLayers);
732 
733                 beginRendering(m_vk, *m_cmdBuffer, *m_colorTargetView, renderArea, clearColor,
734                                vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ATTACHMENT_LOAD_OP_LOAD, 0u, layerCount, viewMask);
735                 draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer,
736                      (m_indexes.size() * sizeof(uint32_t)), firstInstance, instanceCount);
737                 endRendering(m_vk, *m_cmdBuffer);
738 
739                 endCommandBuffer(m_vk, *m_cmdBuffer);
740             }
741 #endif // CTS_USES_VULKANSC
742 
743             if (!m_params.groupParams->useDynamicRendering)
744             {
745                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
746                 preRenderCommands(clearColor, numLayers);
747 
748                 beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
749                 draw(*m_cmdBuffer, vertexBuffer->object(), instancedVertexBuffer->object(), indexBuffer, indirectBuffer,
750                      (m_indexes.size() * sizeof(uint32_t)), firstInstance, instanceCount);
751                 endRenderPass(m_vk, *m_cmdBuffer);
752 
753                 endCommandBuffer(m_vk, *m_cmdBuffer);
754             }
755 
756             /*
757 
758             void InstancedDrawInstance::beginRender(vk::VkCommandBuffer cmdBuffer, const vk::VkClearValue& clearColor, vk::VkRenderingFlagsKHR renderingFlags)
759             {
760 
761                 if (m_params.groupParams->useDynamicRendering)
762                 else
763             */
764 
765             submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
766             m_context.resetCommandPoolForVKSC(device, *m_cmdPool);
767 
768             // Reference rendering
769             std::vector<tcu::Vec4> vetrices;
770             std::vector<tcu::Vec4> colors;
771 
772             for (std::vector<VertexPositionAndColor>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
773             {
774                 vetrices.push_back(it->position);
775                 colors.push_back(it->color);
776             }
777 
778             tcu::TextureLevel refImage(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH),
779                                        (int)(0.5 + HEIGHT));
780 
781             tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
782 
783             const TestVertShader vertShader(instanceCount, firstInstance);
784             const TestFragShader fragShader;
785             const rr::Program program(&vertShader, &fragShader);
786             const rr::MultisamplePixelBufferAccess colorBuffer =
787                 rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
788             const rr::RenderTarget renderTarget(colorBuffer);
789             const rr::RenderState renderState((rr::ViewportState(colorBuffer)),
790                                               m_context.getDeviceProperties().limits.subPixelPrecisionBits);
791             const rr::Renderer renderer;
792 
793             const rr::VertexAttrib vertexAttribs[] = {
794                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vetrices[0]),
795                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]),
796                 // The reference renderer treats a divisor of 0 as meaning per-vertex.  Use INT_MAX instead; it should work just as well.
797                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4),
798                                  (m_params.testAttribDivisor != ATTRIBUTE_DIVISOR_NONE) ?
799                                      (m_params.attribDivisor == 0 ? INT_MAX : m_params.attribDivisor) :
800                                      1,
801                                  &m_instancedColor[0])};
802 
803             if (m_params.function == TestParams::FUNCTION_DRAW ||
804                 m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
805             {
806                 const rr::PrimitiveList primitives =
807                     rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)vetrices.size(), 0);
808                 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
809                                               &vertexAttribs[0], primitives);
810                 renderer.drawInstanced(command, instanceCount);
811             }
812             else
813             {
814                 const rr::DrawIndices indicies(m_indexes.data());
815 
816                 const rr::PrimitiveList primitives =
817                     rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)m_indexes.size(), indicies);
818                 const rr::DrawCommand command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs),
819                                               &vertexAttribs[0], primitives);
820                 renderer.drawInstanced(command, instanceCount);
821             }
822 
823             const vk::VkOffset3D zeroOffset = {0, 0, 0};
824             for (uint32_t i = 0; i < numLayers; i++)
825             {
826                 const tcu::ConstPixelBufferAccess renderedFrame =
827                     m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
828                                                     zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, i);
829 
830                 tcu::TestLog &log = m_context.getTestContext().getLog();
831 
832                 std::ostringstream resultDesc;
833                 resultDesc << "Image layer " << i << " comparison result. Instance count: " << instanceCount
834                            << " first instance index: " << firstInstance;
835 
836                 if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
837                 {
838                     const bool ok = tcu::intThresholdPositionDeviationCompare(
839                         log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
840                         tcu::UVec4(4u),      // color threshold
841                         tcu::IVec3(1, 1, 0), // position deviation tolerance
842                         true,                // don't check the pixels at the boundary
843                         tcu::COMPARE_LOG_RESULT);
844 
845                     if (!ok)
846                         res = QP_TEST_RESULT_FAIL;
847                 }
848                 else
849                 {
850                     if (!tcu::fuzzyCompare(log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
851                                            0.05f, tcu::COMPARE_LOG_RESULT))
852                         res = QP_TEST_RESULT_FAIL;
853                 }
854             }
855         }
856     }
857     return tcu::TestStatus(res, qpGetTestResultName(res));
858 }
859 
prepareVertexData(int instanceCount,int firstInstance,int instanceDivisor)860 void InstancedDrawInstance::prepareVertexData(int instanceCount, int firstInstance, int instanceDivisor)
861 {
862     m_data.clear();
863     m_indexes.clear();
864     m_instancedColor.clear();
865 
866     if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
867     {
868         for (int y = 0; y < QUAD_GRID_SIZE; y++)
869         {
870             for (int x = 0; x < QUAD_GRID_SIZE; x++)
871             {
872                 const float fx0 = -1.0f + (float)(x + 0) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
873                 const float fx1 = -1.0f + (float)(x + 1) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
874                 const float fy0 = -1.0f + (float)(y + 0) / (float)QUAD_GRID_SIZE * 2.0f;
875                 const float fy1 = -1.0f + (float)(y + 1) / (float)QUAD_GRID_SIZE * 2.0f;
876 
877                 // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
878                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
879                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
880                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
881 
882                 // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
883                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
884                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
885                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
886             }
887         }
888     }
889     else
890     {
891         for (int y = 0; y < QUAD_GRID_SIZE + 1; y++)
892         {
893             for (int x = 0; x < QUAD_GRID_SIZE + 1; x++)
894             {
895                 const float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
896                 const float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f;
897 
898                 m_data.push_back(VertexPositionAndColor(
899                     tcu::Vec4(fx, fy, 1.0f, 1.0f), (y % 2 ? tcu::RGBA::blue().toVec() : tcu::RGBA::green().toVec())));
900             }
901         }
902 
903         for (int y = 0; y < QUAD_GRID_SIZE; y++)
904         {
905             for (int x = 0; x < QUAD_GRID_SIZE; x++)
906             {
907                 const int ndx00 = y * (QUAD_GRID_SIZE + 1) + x;
908                 const int ndx10 = y * (QUAD_GRID_SIZE + 1) + x + 1;
909                 const int ndx01 = (y + 1) * (QUAD_GRID_SIZE + 1) + x;
910                 const int ndx11 = (y + 1) * (QUAD_GRID_SIZE + 1) + x + 1;
911 
912                 // Lower-left triangle of a quad.
913                 m_indexes.push_back((uint16_t)ndx00);
914                 m_indexes.push_back((uint16_t)ndx10);
915                 m_indexes.push_back((uint16_t)ndx01);
916 
917                 // Upper-right triangle of a quad.
918                 m_indexes.push_back((uint16_t)ndx11);
919                 m_indexes.push_back((uint16_t)ndx01);
920                 m_indexes.push_back((uint16_t)ndx10);
921             }
922         }
923     }
924 
925     const int colorCount =
926         instanceDivisor == 0 ? 1 : (instanceCount + firstInstance + instanceDivisor - 1) / instanceDivisor;
927     for (int i = 0; i < instanceCount + firstInstance; i++)
928     {
929         m_instancedColor.push_back(tcu::Vec4(0.0, (float)(1.0 - i * 1.0 / colorCount) / 2, 0.0, 1.0));
930     }
931 }
932 
preRenderCommands(const vk::VkClearValue & clearColor,uint32_t numLayers)933 void InstancedDrawInstance::preRenderCommands(const vk::VkClearValue &clearColor, uint32_t numLayers)
934 {
935     const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, numLayers);
936 
937     if (m_params.testMultiview)
938     {
939         vk::VkImageMemoryBarrier barrier{
940             vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
941             DE_NULL,                                    // const void* pNext;
942             0u,                                         // VkAccessFlags srcAccessMask;
943             vk::VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
944             vk::VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
945             vk::VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
946             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t srcQueueFamilyIndex;
947             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t dstQueueFamilyIndex;
948             m_colorTargetImage->object(),               // VkImage image;
949             subresourceRange                            // VkImageSubresourceRange subresourceRange;
950         };
951 
952         m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
953                                 (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
954                                 (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &barrier);
955     }
956     else
957     {
958         initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
959                                       vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
960     }
961 
962     m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor.color,
963                             1, &subresourceRange);
964 
965     const vk::VkMemoryBarrier memBarrier{
966         vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, vk::VK_ACCESS_TRANSFER_WRITE_BIT,
967         vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT};
968 
969     m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
970                             vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0,
971                             DE_NULL);
972 }
973 
cmdBindIndexBufferImpl(vk::VkCommandBuffer commandBuffer,vk::VkBuffer indexBuffer,vk::VkDeviceSize offset,vk::VkDeviceSize size,vk::VkIndexType indexType)974 void InstancedDrawInstance::cmdBindIndexBufferImpl(vk::VkCommandBuffer commandBuffer, vk::VkBuffer indexBuffer,
975                                                    vk::VkDeviceSize offset, vk::VkDeviceSize size,
976                                                    vk::VkIndexType indexType)
977 {
978 #ifndef CTS_USES_VULKANSC
979     if (m_params.useMaintenance5Ext)
980         m_vk.cmdBindIndexBuffer2KHR(commandBuffer, indexBuffer, offset, size, indexType);
981     else
982 #endif
983     {
984         DE_UNREF(size);
985         m_vk.cmdBindIndexBuffer(commandBuffer, indexBuffer, offset, indexType);
986     }
987 }
988 
draw(vk::VkCommandBuffer cmdBuffer,vk::VkBuffer vertexBuffer,vk::VkBuffer instancedVertexBuffer,de::SharedPtr<Buffer> indexBuffer,de::SharedPtr<Buffer> indirectBuffer,vk::VkDeviceSize indexBufferSize,uint32_t firstInstance,uint32_t instanceCount)989 void InstancedDrawInstance::draw(vk::VkCommandBuffer cmdBuffer, vk::VkBuffer vertexBuffer,
990                                  vk::VkBuffer instancedVertexBuffer, de::SharedPtr<Buffer> indexBuffer,
991                                  de::SharedPtr<Buffer> indirectBuffer, vk::VkDeviceSize indexBufferSize,
992                                  uint32_t firstInstance, uint32_t instanceCount)
993 {
994     if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED ||
995         m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
996         cmdBindIndexBufferImpl(cmdBuffer, indexBuffer->object(), 0, indexBufferSize, vk::VK_INDEX_TYPE_UINT32);
997 
998     const vk::VkBuffer vertexBuffers[]{vertexBuffer, instancedVertexBuffer};
999     const vk::VkDeviceSize vertexBufferOffsets[]{0, 0};
1000 
1001     m_vk.cmdBindVertexBuffers(cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
1002 
1003     const float pushConstants[] = {(float)firstInstance, (float)instanceCount};
1004     m_vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u,
1005                           (uint32_t)sizeof(pushConstants), pushConstants);
1006     m_vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
1007 
1008     if (m_params.dynamicState)
1009     {
1010         vk::VkVertexInputBindingDescription2EXT vertexBindingDescription[2]{
1011             {vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, 0, 0u,
1012              (uint32_t)sizeof(VertexPositionAndColor), vk::VK_VERTEX_INPUT_RATE_VERTEX, 1},
1013             {vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, 0, 1u, (uint32_t)sizeof(tcu::Vec4),
1014              vk::VK_VERTEX_INPUT_RATE_INSTANCE, m_params.attribDivisor},
1015 
1016         };
1017         vk::VkVertexInputAttributeDescription2EXT vertexAttributeDescription[3]{
1018             {vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, 0, 0u, 0u,
1019              vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
1020             {
1021                 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
1022                 0,
1023                 1u,
1024                 0u,
1025                 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
1026                 (uint32_t)sizeof(tcu::Vec4),
1027             },
1028             {
1029                 vk::VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
1030                 0,
1031                 2u,
1032                 1u,
1033                 vk::VK_FORMAT_R32G32B32A32_SFLOAT,
1034                 0,
1035             }};
1036 
1037         m_vk.cmdSetVertexInputEXT(cmdBuffer, 2, vertexBindingDescription, 3, vertexAttributeDescription);
1038     }
1039 
1040     switch (m_params.function)
1041     {
1042     case TestParams::FUNCTION_DRAW:
1043         m_vk.cmdDraw(cmdBuffer, (uint32_t)m_data.size(), instanceCount, 0u, firstInstance);
1044         break;
1045 
1046     case TestParams::FUNCTION_DRAW_INDEXED:
1047         m_vk.cmdDrawIndexed(cmdBuffer, (uint32_t)m_indexes.size(), instanceCount, 0u, 0u, firstInstance);
1048         break;
1049 
1050     case TestParams::FUNCTION_DRAW_INDIRECT:
1051         m_vk.cmdDrawIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1052         break;
1053 
1054     case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
1055         m_vk.cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
1056         break;
1057 
1058     default:
1059         DE_ASSERT(false);
1060     }
1061 }
1062 
1063 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)1064 void InstancedDrawInstance::beginSecondaryCmdBuffer(vk::VkRenderingFlagsKHR renderingFlags)
1065 {
1066     const vk::VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
1067         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
1068         DE_NULL,                                                             // const void* pNext;
1069         renderingFlags,                                                      // VkRenderingFlagsKHR flags;
1070         (m_params.testMultiview) ? 3u : 0u,                                  // uint32_t viewMask;
1071         1u,                                                                  // uint32_t colorAttachmentCount;
1072         &m_colorAttachmentFormat,                                            // const VkFormat* pColorAttachmentFormats;
1073         vk::VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
1074         vk::VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
1075         vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1076     };
1077 
1078     const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo{
1079         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
1080         &inheritanceRenderingInfo,                             // const void* pNext;
1081         DE_NULL,                                               // VkRenderPass renderPass;
1082         0u,                                                    // uint32_t subpass;
1083         DE_NULL,                                               // VkFramebuffer framebuffer;
1084         VK_FALSE,                                              // VkBool32 occlusionQueryEnable;
1085         (vk::VkQueryControlFlags)0u,                           // VkQueryControlFlags queryFlags;
1086         (vk::VkQueryPipelineStatisticFlags)0u                  // VkQueryPipelineStatisticFlags pipelineStatistics;
1087     };
1088 
1089     vk::VkCommandBufferUsageFlags usageFlags = vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1090     if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1091         usageFlags |= vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1092 
1093     const vk::VkCommandBufferBeginInfo commandBufBeginParams{
1094         vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1095         DE_NULL,                                         // const void* pNext;
1096         usageFlags,                                      // VkCommandBufferUsageFlags flags;
1097         &bufferInheritanceInfo};
1098 
1099     VK_CHECK(m_vk.beginCommandBuffer(*m_secCmdBuffer, &commandBufBeginParams));
1100 }
1101 #endif // CTS_USES_VULKANSC
1102 
1103 } // namespace
1104 
InstancedTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1105 InstancedTests::InstancedTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
1106     : TestCaseGroup(testCtx, "instanced")
1107     , m_groupParams(groupParams)
1108 {
1109     static const vk::VkPrimitiveTopology topologies[] = {
1110         vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,     vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
1111         vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,     vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
1112         vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1113     };
1114     static const TestParams::DrawFunction functions[] = {
1115         TestParams::FUNCTION_DRAW,
1116         TestParams::FUNCTION_DRAW_INDEXED,
1117         TestParams::FUNCTION_DRAW_INDIRECT,
1118         TestParams::FUNCTION_DRAW_INDEXED_INDIRECT,
1119     };
1120     static const AttributeDivisor attribDivisors[] = {
1121         ATTRIBUTE_DIVISOR_NONE,
1122         ATTRIBUTE_DIVISOR_EXT,
1123 #ifndef CTS_USES_VULKANSC
1124         ATTRIBUTE_DIVISOR_KHR,
1125 #endif
1126     };
1127 
1128     static const bool multiviews[] = {false, true};
1129 
1130     static const uint32_t divisors[] = {0, 1, 2, 4, 20};
1131     for (int dynState = 0; dynState < 2; dynState++)
1132     {
1133         for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); topologyNdx++)
1134         {
1135             // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1136             if (groupParams->useSecondaryCmdBuffer && (topologyNdx % 2u))
1137                 continue;
1138 
1139             for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(functions); functionNdx++)
1140             {
1141                 for (int testAttribDivisor = 0; testAttribDivisor < DE_LENGTH_OF_ARRAY(attribDivisors);
1142                      testAttribDivisor++)
1143                 {
1144                     AttributeDivisor attribDivisor = attribDivisors[testAttribDivisor];
1145                     for (int divisorNdx = 0; divisorNdx < DE_LENGTH_OF_ARRAY(divisors); divisorNdx++)
1146                     {
1147                         // reduce number of tests for dynamic rendering cases where secondary command buffer is used
1148                         if (groupParams->useSecondaryCmdBuffer && (divisorNdx % 2u))
1149                             continue;
1150 
1151                         for (int multiviewNdx = 0; multiviewNdx < DE_LENGTH_OF_ARRAY(multiviews); multiviewNdx++)
1152                         {
1153                             // If we don't have VK_EXT_vertex_attribute_divisor or VK_KHR_vertex_attribute_divisor, we only get a divisor or 1.
1154                             if (attribDivisor == ATTRIBUTE_DIVISOR_NONE && divisors[divisorNdx] != 1)
1155                                 continue;
1156 
1157                             TestParams param{
1158                                 functions[functionNdx],       // DrawFunction function;
1159                                 topologies[topologyNdx],      // vk::VkPrimitiveTopology topology;
1160                                 groupParams,                  // const SharedGroupParams groupParams;
1161                                 attribDivisor,                // AttributeDivisor testAttribDivisor;
1162                                 divisors[divisorNdx],         // uint32_t attribDivisor;
1163                                 multiviews[multiviewNdx],     // bool testMultiview;
1164                                 dynState == 0 ? false : true, // bool dynamicState;
1165                                 false                         // bool useMaintenance5Ext;
1166                             };
1167 
1168                             // Add multiview tests only when vertex attribute divisor is enabled.
1169                             if (param.testMultiview && !testAttribDivisor)
1170                                 continue;
1171 
1172                             std::string testName = de::toString(param);
1173 
1174                             addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), param));
1175 
1176 #ifndef CTS_USES_VULKANSC
1177                             if (TestParams::FUNCTION_DRAW_INDEXED == functions[functionNdx] ||
1178                                 TestParams::FUNCTION_DRAW_INDEXED_INDIRECT == functions[functionNdx])
1179                             {
1180                                 param.useMaintenance5Ext = true;
1181                                 testName += "_maintenance_5";
1182                                 // Instanced drawing test using vkCmdBindIndexBuffer2KHR() introduced in VK_KHR_maintenance5
1183                                 addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), param));
1184                             }
1185 #endif // CTS_USES_VULKANSC
1186                         }
1187                     }
1188                 }
1189             }
1190         }
1191     }
1192 }
1193 
~InstancedTests()1194 InstancedTests::~InstancedTests()
1195 {
1196 }
1197 
1198 } // namespace Draw
1199 } // namespace vkt
1200