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