Merge "Fix missing SSBO binding in EGL robustness tests"
[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 "deSharedPtr.hpp"
28 #include "rrRenderer.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRGBA.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vktDrawBufferObjectUtil.hpp"
35 #include "vktDrawCreateInfoUtil.hpp"
36 #include "vktDrawImageObjectUtil.hpp"
37 #include "vktDrawTestCaseUtil.hpp"
38
39 namespace vkt
40 {
41 namespace Draw
42 {
43 namespace
44 {
45
46 static const int        QUAD_GRID_SIZE  = 8;
47 static const int        WIDTH                   = 128;
48 static const int        HEIGHT                  = 128;
49
50 struct TestParams
51 {
52         enum DrawFunction
53         {
54                 FUNCTION_DRAW = 0,
55                 FUNCTION_DRAW_INDEXED,
56                 FUNCTION_DRAW_INDIRECT,
57                 FUNCTION_DRAW_INDEXED_INDIRECT,
58
59                 FUNTION_LAST
60         };
61
62         DrawFunction                    function;
63         vk::VkPrimitiveTopology topology;
64 };
65
66 struct VertexPositionAndColor
67 {
68                                 VertexPositionAndColor (tcu::Vec4 position_, tcu::Vec4 color_)
69                                         : position      (position_)
70                                         , color         (color_)
71                                 {
72                                 }
73
74         tcu::Vec4       position;
75         tcu::Vec4       color;
76 };
77
78 std::ostream & operator<<(std::ostream & str, TestParams const & v)
79 {
80         std::ostringstream string;
81         switch (v.function)
82         {
83                 case TestParams::FUNCTION_DRAW:
84                         string << "draw";
85                         break;
86                 case TestParams::FUNCTION_DRAW_INDEXED:
87                         string << "draw_indexed";
88                         break;
89                 case TestParams::FUNCTION_DRAW_INDIRECT:
90                         string << "draw_indirect";
91                         break;
92                 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
93                         string << "draw_indexed_indirect";
94                         break;
95                 default:
96                         DE_ASSERT(false);
97         }
98
99         string << "_" << de::toString(v.topology);
100         return str << string.str();
101 }
102
103 rr::PrimitiveType mapVkPrimitiveTopology (vk::VkPrimitiveTopology primitiveTopology)
104 {
105         switch (primitiveTopology)
106         {
107                 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:                                              return rr::PRIMITIVETYPE_POINTS;
108                 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:                                               return rr::PRIMITIVETYPE_LINES;
109                 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:                                              return rr::PRIMITIVETYPE_LINE_STRIP;
110                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:                                   return rr::PRIMITIVETYPE_TRIANGLES;
111                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:                                    return rr::PRIMITIVETYPE_TRIANGLE_FAN;
112                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:                                  return rr::PRIMITIVETYPE_TRIANGLE_STRIP;
113                 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:                return rr::PRIMITIVETYPE_LINES_ADJACENCY;
114                 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:               return rr::PRIMITIVETYPE_LINE_STRIP_ADJACENCY;
115                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:    return rr::PRIMITIVETYPE_TRIANGLES_ADJACENCY;
116                 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:   return rr::PRIMITIVETYPE_TRIANGLE_STRIP_ADJACENCY;
117                 default:
118                         DE_ASSERT(false);
119         }
120         return rr::PRIMITIVETYPE_LAST;
121 }
122
123 template<typename T>
124 de::SharedPtr<Buffer> createAndUploadBuffer(const std::vector<T> data, const vk::DeviceInterface& vk, const Context& context)
125 {
126         const vk::VkDeviceSize dataSize = data.size() * sizeof(T);
127         de::SharedPtr<Buffer> vertexBuffer = Buffer::createAndAlloc(vk, context.getDevice(),
128                                                                                                                                 BufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
129                                                                                                                                 context.getDefaultAllocator(),
130                                                                                                                                 vk::MemoryRequirement::HostVisible);
131
132         deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
133
134         deMemcpy(ptr, &data[0], static_cast<size_t>(dataSize));
135
136         vk::flushMappedMemoryRange(vk, context.getDevice(),
137                                                            vertexBuffer->getBoundMemory().getMemory(),
138                                                            vertexBuffer->getBoundMemory().getOffset(),
139                                                            VK_WHOLE_SIZE);
140         return vertexBuffer;
141 }
142
143 class TestVertShader : public rr::VertexShader
144 {
145 public:
146         TestVertShader (int numInstances, int firstInstance)
147                 : rr::VertexShader      (3, 1)
148                 , m_numInstances        (numInstances)
149                 , m_firstInstance       (firstInstance)
150         {
151                 m_inputs[0].type        = rr::GENERICVECTYPE_FLOAT;
152                 m_inputs[1].type        = rr::GENERICVECTYPE_FLOAT;
153                 m_inputs[2].type        = rr::GENERICVECTYPE_FLOAT;
154                 m_outputs[0].type       = rr::GENERICVECTYPE_FLOAT;
155         }
156
157         void shadeVertices (const rr::VertexAttrib* inputs,
158                                                 rr::VertexPacket* const* packets,
159                                                 const int numPackets) const
160         {
161                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
162                 {
163                         const int               instanceNdx             = packets[packetNdx]->instanceNdx + m_firstInstance;
164                         const tcu::Vec4 position                = rr::readVertexAttribFloat(inputs[0], instanceNdx,     packets[packetNdx]->vertexNdx);
165                         const tcu::Vec4 color                   = rr::readVertexAttribFloat(inputs[1], instanceNdx,     packets[packetNdx]->vertexNdx);
166                         const tcu::Vec4 color2                  = rr::readVertexAttribFloat(inputs[2], instanceNdx, packets[packetNdx]->vertexNdx);
167                         packets[packetNdx]->position    = position + tcu::Vec4((float)(packets[packetNdx]->instanceNdx * 2.0 / m_numInstances), 0.0, 0.0, 0.0);
168                         packets[packetNdx]->outputs[0]  = color + tcu::Vec4((float)instanceNdx / (float)m_numInstances, 0.0, 0.0, 1.0) + color2;
169                 }
170         }
171
172 private:
173         const int m_numInstances;
174         const int m_firstInstance;
175 };
176
177 class TestFragShader : public rr::FragmentShader
178 {
179 public:
180         TestFragShader (void)
181                 : rr::FragmentShader(1, 1)
182         {
183                 m_inputs[0].type        = rr::GENERICVECTYPE_FLOAT;
184                 m_outputs[0].type       = rr::GENERICVECTYPE_FLOAT;
185         }
186
187         void shadeFragments (rr::FragmentPacket* packets,
188                                                  const int numPackets,
189                                                  const rr::FragmentShadingContext& context) const
190         {
191                 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
192                 {
193                         rr::FragmentPacket& packet = packets[packetNdx];
194                         for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
195                         {
196                                 const tcu::Vec4 color = rr::readVarying<float>(packet, context, 0, fragNdx);
197                                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
198                         }
199                 }
200         }
201 };
202
203 class InstancedDrawInstance : public TestInstance
204 {
205 public:
206                                                                                                 InstancedDrawInstance   (Context& context, TestParams params);
207         virtual tcu::TestStatus                                         iterate                                 (void);
208
209 private:
210         void                                                                            prepareVertexData               (int instanceCount, int firstInstance);
211
212         const TestParams                                                        m_params;
213         const vk::DeviceInterface&                                      m_vk;
214
215         vk::VkFormat                                                            m_colorAttachmentFormat;
216
217         vk::Move<vk::VkPipeline>                                        m_pipeline;
218         vk::Move<vk::VkPipelineLayout>                          m_pipelineLayout;
219
220         de::SharedPtr<Image>                                            m_colorTargetImage;
221         vk::Move<vk::VkImageView>                                       m_colorTargetView;
222
223         PipelineCreateInfo::VertexInputState            m_vertexInputState;
224
225         vk::Move<vk::VkCommandPool>                                     m_cmdPool;
226         vk::Move<vk::VkCommandBuffer>                           m_cmdBuffer;
227
228         vk::Move<vk::VkFramebuffer>                                     m_framebuffer;
229         vk::Move<vk::VkRenderPass>                                      m_renderPass;
230
231         // Vertex data
232         std::vector<VertexPositionAndColor>                     m_data;
233         std::vector<deUint32>                                           m_indexes;
234         std::vector<tcu::Vec4>                                          m_instancedColor;
235 };
236
237 class InstancedDrawCase : public TestCase
238 {
239 public:
240         InstancedDrawCase (tcu::TestContext&    testCtx,
241                                            const std::string&   name,
242                                            const std::string&   desc,
243                                            TestParams                   params)
244                 : TestCase      (testCtx, name, desc)
245                 , m_params      (params)
246         {
247                 m_vertexShader = "#version 430\n"
248                                 "layout(location = 0) in vec4 in_position;\n"
249                                 "layout(location = 1) in vec4 in_color;\n"
250                                 "layout(location = 2) in vec4 in_color_2;\n"
251                                 "layout(push_constant) uniform TestParams {\n"
252                                 "       float firstInstance;\n"
253                                 "       float instanceCount;\n"
254                                 "} params;\n"
255                                 "layout(location = 0) out vec4 out_color;\n"
256                                 "out gl_PerVertex {\n"
257                                 "    vec4  gl_Position;\n"
258                                 "    float gl_PointSize;\n"
259                                 "};\n"
260                                 "void main() {\n"
261                                 "    gl_PointSize = 1.0;\n"
262                                 "    gl_Position  = in_position + vec4(float(gl_InstanceIndex - params.firstInstance) * 2.0 / params.instanceCount, 0.0, 0.0, 0.0);\n"
263                                 "    out_color    = in_color + vec4(float(gl_InstanceIndex) / params.instanceCount, 0.0, 0.0, 1.0) + in_color_2;\n"
264                                 "}\n";
265
266                 m_fragmentShader = "#version 430\n"
267                                 "layout(location = 0) in vec4 in_color;\n"
268                                 "layout(location = 0) out vec4 out_color;\n"
269                                 "void main()\n"
270                                 "{\n"
271                                 "    out_color = in_color;\n"
272                                 "}\n";
273         }
274
275         TestInstance* createInstance (Context& context) const
276         {
277                 return new InstancedDrawInstance(context, m_params);
278         }
279
280         virtual void initPrograms (vk::SourceCollections& programCollection) const
281         {
282                 programCollection.glslSources.add("InstancedDrawVert") << glu::VertexSource(m_vertexShader);
283                 programCollection.glslSources.add("InstancedDrawFrag") << glu::FragmentSource(m_fragmentShader);
284         }
285
286 private:
287         const TestParams        m_params;
288         std::string                     m_vertexShader;
289         std::string                     m_fragmentShader;
290 };
291
292 InstancedDrawInstance::InstancedDrawInstance(Context &context, TestParams params)
293         : TestInstance                          (context)
294         , m_params                                      (params)
295         , m_vk                                          (context.getDeviceInterface())
296         , m_colorAttachmentFormat       (vk::VK_FORMAT_R8G8B8A8_UNORM)
297 {
298         const vk::VkDevice device                               = m_context.getDevice();
299         const deUint32 queueFamilyIndex                 = m_context.getUniversalQueueFamilyIndex();
300
301         const vk::VkPushConstantRange pushConstantRange = {
302                 vk::VK_SHADER_STAGE_VERTEX_BIT,                         // VkShaderStageFlags    stageFlags;
303                 0u,                                                                                     // uint32_t              offset;
304                 (deUint32)sizeof(float) * 2,                            // uint32_t              size;
305         };
306
307         const PipelineLayoutCreateInfo pipelineLayoutCreateInfo(0, DE_NULL, 1, &pushConstantRange);
308         m_pipelineLayout                                                = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
309
310         const vk::VkExtent3D targetImageExtent  = { WIDTH, HEIGHT, 1 };
311         const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
312                 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);
313
314         m_colorTargetImage                                              = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
315
316         const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
317         m_colorTargetView                                               = vk::createImageView(m_vk, device, &colorTargetViewInfo);
318
319         RenderPassCreateInfo renderPassCreateInfo;
320         renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
321                                                                                                                          vk::VK_SAMPLE_COUNT_1_BIT,
322                                                                                                                          vk::VK_ATTACHMENT_LOAD_OP_LOAD,
323                                                                                                                          vk::VK_ATTACHMENT_STORE_OP_STORE,
324                                                                                                                          vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
325                                                                                                                          vk::VK_ATTACHMENT_STORE_OP_STORE,
326                                                                                                                          vk::VK_IMAGE_LAYOUT_GENERAL,
327                                                                                                                          vk::VK_IMAGE_LAYOUT_GENERAL));
328
329         const vk::VkAttachmentReference colorAttachmentReference =
330         {
331                 0,
332                 vk::VK_IMAGE_LAYOUT_GENERAL
333         };
334
335         renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
336                                                                                                            0,
337                                                                                                            0,
338                                                                                                            DE_NULL,
339                                                                                                            1,
340                                                                                                            &colorAttachmentReference,
341                                                                                                            DE_NULL,
342                                                                                                            AttachmentReference(),
343                                                                                                            0,
344                                                                                                            DE_NULL));
345
346         m_renderPass            = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
347
348         std::vector<vk::VkImageView> colorAttachments(1);
349         colorAttachments[0] = *m_colorTargetView;
350
351         const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
352
353         m_framebuffer           = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
354
355         const vk::VkVertexInputBindingDescription vertexInputBindingDescription[2] =
356         {
357                 {
358                         0u,
359                         (deUint32)sizeof(VertexPositionAndColor),
360                         vk::VK_VERTEX_INPUT_RATE_VERTEX,
361                 },
362                 {
363                         1u,
364                         (deUint32)sizeof(tcu::Vec4),
365                         vk::VK_VERTEX_INPUT_RATE_INSTANCE,
366                 },
367         };
368
369         const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
370         {
371                 {
372                         0u,
373                         0u,
374                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,
375                         0u
376                 },
377                 {
378                         1u,
379                         0u,
380                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,
381                         (deUint32)sizeof(tcu::Vec4),
382                 },
383                 {
384                         2u,
385                         1u,
386                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,
387                         0,
388                 }
389         };
390
391         m_vertexInputState = PipelineCreateInfo::VertexInputState(2,
392                                                                                                                           vertexInputBindingDescription,
393                                                                                                                           DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),
394                                                                                                                           vertexInputAttributeDescriptions);
395
396         const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
397         m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
398
399         m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
400
401         const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawVert"), 0));
402         const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("InstancedDrawFrag"), 0));
403
404         const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
405
406         vk::VkViewport viewport;
407         viewport.x                              = 0;
408         viewport.y                              = 0;
409         viewport.width                  = static_cast<float>(WIDTH);
410         viewport.height                 = static_cast<float>(HEIGHT);
411         viewport.minDepth               = 0.0f;
412         viewport.maxDepth               = 1.0f;
413
414         vk::VkRect2D scissor;
415         scissor.offset.x                = 0;
416         scissor.offset.y                = 0;
417         scissor.extent.width    = WIDTH;
418         scissor.extent.height   = HEIGHT;
419
420         PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
421         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
422         pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
423         pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
424         pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_params.topology));
425         pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
426         pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
427         pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
428         pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
429         pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
430
431         m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
432 }
433
434 tcu::TestStatus InstancedDrawInstance::iterate()
435 {
436         const vk::VkQueue               queue                                   = m_context.getUniversalQueue();
437         static const deUint32   instanceCounts[]                = { 1, 2, 4, 20 };
438         static const deUint32   firstInstanceIndices[]  = { 0, 1, 3, 4, 20 };
439
440         qpTestResult                    res                                             = QP_TEST_RESULT_PASS;
441
442         const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
443         const CmdBufferBeginInfo beginInfo;
444         int firstInstanceIndicesCount = 1;
445
446         // Require 'drawIndirectFirstInstance' feature to run non-zero firstInstance indirect draw tests.
447         if (m_context.getDeviceFeatures().drawIndirectFirstInstance)
448                 firstInstanceIndicesCount = DE_LENGTH_OF_ARRAY(firstInstanceIndices);
449
450         for (int instanceCountNdx = 0; instanceCountNdx < DE_LENGTH_OF_ARRAY(instanceCounts); instanceCountNdx++)
451         {
452                 const deUint32 instanceCount = instanceCounts[instanceCountNdx];
453                 for (int firstInstanceIndexNdx = 0; firstInstanceIndexNdx < firstInstanceIndicesCount; firstInstanceIndexNdx++)
454                 {
455                         const deUint32 firstInstance = firstInstanceIndices[firstInstanceIndexNdx];
456
457                         prepareVertexData(instanceCount, firstInstance);
458                         const de::SharedPtr<Buffer>     vertexBuffer                    = createAndUploadBuffer(m_data, m_vk, m_context);
459                         const de::SharedPtr<Buffer>     instancedVertexBuffer   = createAndUploadBuffer(m_instancedColor, m_vk, m_context);
460                         de::SharedPtr<Buffer>           indexBuffer;
461                         de::SharedPtr<Buffer>           indirectBuffer;
462                         m_vk.beginCommandBuffer(*m_cmdBuffer, &beginInfo);
463
464                         initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL);
465
466                         const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
467                         m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
468                                 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
469
470                         const vk::VkMemoryBarrier memBarrier =
471                         {
472                                 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
473                                 DE_NULL,
474                                 vk::VK_ACCESS_TRANSFER_WRITE_BIT,
475                                 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
476                         };
477
478                         m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
479                                 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
480                                 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
481
482                         const vk::VkRect2D renderArea = { { 0, 0 }, { WIDTH, HEIGHT } };
483                         const RenderPassBeginInfo renderPassBegin(*m_renderPass, *m_framebuffer, renderArea);
484
485                         m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
486
487                         if (m_params.function == TestParams::FUNCTION_DRAW_INDEXED || m_params.function == TestParams::FUNCTION_DRAW_INDEXED_INDIRECT)
488                         {
489                                 indexBuffer = createAndUploadBuffer(m_indexes, m_vk, m_context);
490                                 m_vk.cmdBindIndexBuffer(*m_cmdBuffer, indexBuffer->object(), 0, vk::VK_INDEX_TYPE_UINT32);
491                         }
492
493                         const vk::VkBuffer vertexBuffers[] =
494                         {
495                                 vertexBuffer->object(),
496                                 instancedVertexBuffer->object(),
497                         };
498
499                         const vk::VkDeviceSize vertexBufferOffsets[] =
500                         {
501                                 0,      // vertexBufferOffset
502                                 0,      // instancedVertexBufferOffset
503                         };
504
505                         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers, vertexBufferOffsets);
506
507                         const float pushConstants[] = { (float)firstInstance, (float)instanceCount };
508                         m_vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, vk::VK_SHADER_STAGE_VERTEX_BIT, 0u, (deUint32)sizeof(pushConstants), pushConstants);
509
510                         m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
511
512                         switch (m_params.function)
513                         {
514                                 case TestParams::FUNCTION_DRAW:
515                                         m_vk.cmdDraw(*m_cmdBuffer, (deUint32)m_data.size(), instanceCount, 0u, firstInstance);
516                                         break;
517
518                                 case TestParams::FUNCTION_DRAW_INDEXED:
519                                         m_vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indexes.size(), instanceCount, 0u, 0u, firstInstance);
520                                         break;
521
522                                 case TestParams::FUNCTION_DRAW_INDIRECT:
523                                 {
524                                         vk::VkDrawIndirectCommand drawCommand =
525                                         {
526                                                 (deUint32)m_data.size(),        // uint32_t     vertexCount;
527                                                 instanceCount,                          // uint32_t     instanceCount;
528                                                 0u,                                                     // uint32_t     firstVertex;
529                                                 firstInstance,                          // uint32_t     firstInstance;
530                                         };
531                                         std::vector<vk::VkDrawIndirectCommand> drawCommands;
532                                         drawCommands.push_back(drawCommand);
533                                         indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context);
534
535                                         m_vk.cmdDrawIndirect(*m_cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
536                                         break;
537                                 }
538                                 case TestParams::FUNCTION_DRAW_INDEXED_INDIRECT:
539                                 {
540                                         vk::VkDrawIndexedIndirectCommand drawCommand =
541                                         {
542                                                 (deUint32)m_indexes.size(),     // uint32_t     indexCount;
543                                                 instanceCount,                          // uint32_t     instanceCount;
544                                                 0u,                                                     // uint32_t     firstIndex;
545                                                 0,                                                      // int32_t      vertexOffset;
546                                                 firstInstance,                          // uint32_t     firstInstance;
547                                         };
548                                         std::vector<vk::VkDrawIndexedIndirectCommand> drawCommands;
549                                         drawCommands.push_back(drawCommand);
550                                         indirectBuffer = createAndUploadBuffer(drawCommands, m_vk, m_context);
551
552                                         m_vk.cmdDrawIndexedIndirect(*m_cmdBuffer, indirectBuffer->object(), 0, 1u, 0u);
553                                         break;
554                                 }
555                                 default:
556                                         DE_ASSERT(false);
557                         }
558
559                         m_vk.cmdEndRenderPass(*m_cmdBuffer);
560                         m_vk.endCommandBuffer(*m_cmdBuffer);
561
562                         vk::VkSubmitInfo submitInfo =
563                         {
564                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,                      // VkStructureType                              sType;
565                                 DE_NULL,                                                                        // const void*                                  pNext;
566                                 0,                                                                                      // deUint32                                             waitSemaphoreCount;
567                                 DE_NULL,                                                                        // const VkSemaphore*                   pWaitSemaphores;
568                                 (const vk::VkPipelineStageFlags*)DE_NULL,       // const VkPipelineStageFlags*  pWaitDstStageMask;
569                                 1,                                                                                      // deUint32                                             commandBufferCount;
570                                 &m_cmdBuffer.get(),                                                     // const VkCommandBuffer*               pCommandBuffers;
571                                 0,                                                                                      // deUint32                                             signalSemaphoreCount;
572                                 DE_NULL                                                                         // const VkSemaphore*                   pSignalSemaphores;
573                         };
574                         VK_CHECK(m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL));
575
576                         VK_CHECK(m_vk.queueWaitIdle(queue));
577
578                         // Reference rendering
579                         std::vector<tcu::Vec4>  vetrices;
580                         std::vector<tcu::Vec4>  colors;
581
582                         for (std::vector<VertexPositionAndColor>::const_iterator it = m_data.begin(); it != m_data.end(); ++it)
583                         {
584                                 vetrices.push_back(it->position);
585                                 colors.push_back(it->color);
586                         }
587
588                         tcu::TextureLevel refImage (vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
589
590                         tcu::clear(refImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
591
592                         const TestVertShader                                    vertShader(instanceCount, firstInstance);
593                         const TestFragShader                                    fragShader;
594                         const rr::Program                                               program                 (&vertShader, &fragShader);
595                         const rr::MultisamplePixelBufferAccess  colorBuffer             = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(refImage.getAccess());
596                         const rr::RenderTarget                                  renderTarget    (colorBuffer);
597                         const rr::RenderState                                   renderState             ((rr::ViewportState(colorBuffer)));
598                         const rr::Renderer                                              renderer;
599
600                         const rr::VertexAttrib  vertexAttribs[] =
601                         {
602                                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &vetrices[0]),
603                                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, &colors[0]),
604                                 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 1, &m_instancedColor[0])
605                         };
606
607                         if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
608                         {
609                                 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)vetrices.size(), 0);
610                                 const rr::DrawCommand   command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
611                                                                                                 primitives);
612                                 renderer.drawInstanced(command, instanceCount);
613                         }
614                         else
615                         {
616                                 const rr::DrawIndices indicies(m_indexes.data());
617
618                                 const rr::PrimitiveList primitives = rr::PrimitiveList(mapVkPrimitiveTopology(m_params.topology), (int)m_indexes.size(), indicies);
619                                 const rr::DrawCommand   command(renderState, renderTarget, program, DE_LENGTH_OF_ARRAY(vertexAttribs), &vertexAttribs[0],
620                                                                                                 primitives);
621                                 renderer.drawInstanced(command, instanceCount);
622                         }
623
624                         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
625                         const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
626                                 vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
627
628                         tcu::TestLog &log               = m_context.getTestContext().getLog();
629
630                         std::ostringstream resultDesc;
631                         resultDesc << "Image comparison result. Instance count: " << instanceCount << " first instance index: " << firstInstance;
632
633                         if (m_params.topology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
634                         {
635                                 const bool ok = tcu::intThresholdPositionDeviationCompare(
636                                         log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame,
637                                         tcu::UVec4(4u),                                 // color threshold
638                                         tcu::IVec3(1, 1, 0),                    // position deviation tolerance
639                                         true,                                                   // don't check the pixels at the boundary
640                                         tcu::COMPARE_LOG_RESULT);
641
642                                 if (!ok)
643                                         res = QP_TEST_RESULT_FAIL;
644                         }
645                         else
646                         {
647                                 if (!tcu::fuzzyCompare(log, "Result", resultDesc.str().c_str(), refImage.getAccess(), renderedFrame, 0.05f, tcu::COMPARE_LOG_RESULT))
648                                         res = QP_TEST_RESULT_FAIL;
649                         }
650                 }
651         }
652         return tcu::TestStatus(res, qpGetTestResultName(res));
653 }
654
655 void InstancedDrawInstance::prepareVertexData(int instanceCount, int firstInstance)
656 {
657         m_data.clear();
658         m_indexes.clear();
659         m_instancedColor.clear();
660
661         if (m_params.function == TestParams::FUNCTION_DRAW || m_params.function == TestParams::FUNCTION_DRAW_INDIRECT)
662         {
663                 for (int y = 0; y < QUAD_GRID_SIZE; y++)
664                 {
665                         for (int x = 0; x < QUAD_GRID_SIZE; x++)
666                         {
667                                 const float fx0 = -1.0f + (float)(x+0) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
668                                 const float fx1 = -1.0f + (float)(x+1) / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
669                                 const float fy0 = -1.0f + (float)(y+0) / (float)QUAD_GRID_SIZE * 2.0f;
670                                 const float fy1 = -1.0f + (float)(y+1) / (float)QUAD_GRID_SIZE * 2.0f;
671
672                                 // Vertices of a quad's lower-left triangle: (fx0, fy0), (fx1, fy0) and (fx0, fy1)
673                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
674                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
675                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
676
677                                 // Vertices of a quad's upper-right triangle: (fx1, fy1), (fx0, fy1) and (fx1, fy0)
678                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
679                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx0, fy1, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
680                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx1, fy0, 1.0f, 1.0f), tcu::RGBA::blue().toVec()));
681                         }
682                 }
683         }
684         else
685         {
686                 for (int y = 0; y < QUAD_GRID_SIZE + 1; y++)
687                 {
688                         for (int x = 0; x < QUAD_GRID_SIZE + 1; x++)
689                         {
690                                 const float fx = -1.0f + (float)x / (float)QUAD_GRID_SIZE * 2.0f / (float)instanceCount;
691                                 const float fy = -1.0f + (float)y / (float)QUAD_GRID_SIZE * 2.0f;
692
693                                 m_data.push_back(VertexPositionAndColor(tcu::Vec4(fx, fy, 1.0f, 1.0f),
694                                                                                                                 (y % 2 ? tcu::RGBA::blue().toVec() : tcu::RGBA::green().toVec())));
695                         }
696                 }
697
698                 for (int y = 0; y < QUAD_GRID_SIZE; y++)
699                 {
700                         for (int x = 0; x < QUAD_GRID_SIZE; x++)
701                         {
702                                 const int ndx00 = y*(QUAD_GRID_SIZE + 1) + x;
703                                 const int ndx10 = y*(QUAD_GRID_SIZE + 1) + x + 1;
704                                 const int ndx01 = (y + 1)*(QUAD_GRID_SIZE + 1) + x;
705                                 const int ndx11 = (y + 1)*(QUAD_GRID_SIZE + 1) + x + 1;
706
707                                 // Lower-left triangle of a quad.
708                                 m_indexes.push_back((deUint16)ndx00);
709                                 m_indexes.push_back((deUint16)ndx10);
710                                 m_indexes.push_back((deUint16)ndx01);
711
712                                 // Upper-right triangle of a quad.
713                                 m_indexes.push_back((deUint16)ndx11);
714                                 m_indexes.push_back((deUint16)ndx01);
715                                 m_indexes.push_back((deUint16)ndx10);
716                         }
717                 }
718         }
719
720         for (int i = 0; i < instanceCount + firstInstance; i++)
721         {
722                 m_instancedColor.push_back(tcu::Vec4(0.0, (float)(1.0 - i * 1.0 / (instanceCount + firstInstance)) / 2, 0.0, 1.0));
723         }
724 }
725
726 } // anonymus
727
728 InstancedTests::InstancedTests(tcu::TestContext& testCtx)
729         : TestCaseGroup (testCtx, "instanced", "Instanced drawing tests")
730 {
731         static const vk::VkPrimitiveTopology    topologies[]                    =
732         {
733                 vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
734                 vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
735                 vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
736                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
737                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
738                 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
739         };
740         static const TestParams::DrawFunction   functions[]                             =
741         {
742                 TestParams::FUNCTION_DRAW,
743                 TestParams::FUNCTION_DRAW_INDEXED,
744                 TestParams::FUNCTION_DRAW_INDIRECT,
745                 TestParams::FUNCTION_DRAW_INDEXED_INDIRECT,
746         };
747
748         for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); topologyNdx++)
749         {
750                 for (int functionNdx = 0; functionNdx < DE_LENGTH_OF_ARRAY(functions); functionNdx++)
751                 {
752                         TestParams param;
753                         param.function = functions[functionNdx];
754                         param.topology = topologies[topologyNdx];
755
756                         std::string testName = de::toString(param);
757
758                         addChild(new InstancedDrawCase(m_testCtx, de::toLower(testName), "Instanced drawing test", param));
759                 }
760         }
761 }
762
763 InstancedTests::~InstancedTests() {}
764
765 } // DrawTests
766 } // vkt