dEQP-VK.renderpass: Set IMAGE_USAGE_TRANSFER_SRC_BIT when needed
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelinePushConstantTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Limited.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and/or associated documentation files (the
10  * "Materials"), to deal in the Materials without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Materials, and to
13  * permit persons to whom the Materials are furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice(s) and this permission notice shall be included
17  * in all copies or substantial portions of the Materials.
18  *
19  * The Materials are Confidential Information as defined by the
20  * Khronos Membership Agreement until designated non-confidential by Khronos,
21  * at which point this condition clause shall be removed.
22  *
23  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30  *
31  *//*!
32  * \file
33  * \brief PushConstant Tests
34  *//*--------------------------------------------------------------------*/
35
36 #include "vktPipelinePushConstantTests.hpp"
37 #include "vktPipelineClearUtil.hpp"
38 #include "vktPipelineImageUtil.hpp"
39 #include "vktPipelineVertexUtil.hpp"
40 #include "vktPipelineReferenceRenderer.hpp"
41 #include "vktTestCase.hpp"
42 #include "vkImageUtil.hpp"
43 #include "vkMemUtil.hpp"
44 #include "vkPrograms.hpp"
45 #include "vkQueryUtil.hpp"
46 #include "vkRef.hpp"
47 #include "vkRefUtil.hpp"
48 #include "vkBuilderUtil.hpp"
49 #include "vkTypeUtil.hpp"
50 #include "tcuImageCompare.hpp"
51 #include "deMemory.h"
52 #include "deRandom.hpp"
53 #include "deStringUtil.hpp"
54 #include "deUniquePtr.hpp"
55
56 #include <algorithm>
57 #include <sstream>
58 #include <vector>
59
60 namespace vkt
61 {
62 namespace pipeline
63 {
64
65 using namespace vk;
66
67 namespace
68 {
69
70 enum
71 {
72         TRIANGLE_COUNT  = 2,
73         MAX_RANGE_COUNT = 5
74 };
75
76 enum RangeSizeCase
77 {
78         SIZE_CASE_4     = 0,
79         SIZE_CASE_16,
80         SIZE_CASE_32,
81         SIZE_CASE_48,
82         SIZE_CASE_128,
83         SIZE_CASE_UNSUPPORTED
84 };
85
86 struct PushConstantData
87 {
88         struct PushConstantRange
89         {
90                 VkShaderStageFlags              shaderStage;
91                 deUint32                                offset;
92                 deUint32                                size;
93         } range;
94         struct PushConstantUpdate
95         {
96                 deUint32                                offset;
97                 deUint32                                size;
98         } update;
99 };
100
101 class PushConstantGraphicsTest : public vkt::TestCase
102 {
103 public:
104                                                         PushConstantGraphicsTest        (tcu::TestContext&                      testContext,
105                                                                                                                  const std::string&                     name,
106                                                                                                                  const std::string&                     description,
107                                                                                                                  const deUint32                         rangeCount,
108                                                                                                                  const PushConstantData         pushConstantRange[MAX_RANGE_COUNT],
109                                                                                                                  const deBool                           multipleUpdate);
110         virtual                                 ~PushConstantGraphicsTest       (void);
111         virtual void                    initPrograms                            (SourceCollections& sourceCollections) const;
112         virtual TestInstance*   createInstance                          (Context& context) const;
113         RangeSizeCase                   getRangeSizeCase                        (deUint32 rangeSize) const;
114
115 private:
116         const deUint32                  m_rangeCount;
117         PushConstantData                m_pushConstantRange[MAX_RANGE_COUNT];
118         const deBool                    m_multipleUpdate;
119 };
120
121 class PushConstantGraphicsTestInstance : public vkt::TestInstance
122 {
123 public:
124                                                                 PushConstantGraphicsTestInstance        (Context&                                       context,
125                                                                                                                                          const deUint32                         rangeCount,
126                                                                                                                                          const PushConstantData         pushConstantRange[MAX_RANGE_COUNT],
127                                                                                                                                          const deBool                           multipleUpdate);
128         virtual                                         ~PushConstantGraphicsTestInstance       (void);
129         virtual tcu::TestStatus         iterate                                                         (void);
130
131         void                                            createShaderStage                                       (const DeviceInterface&         vk,
132                                                                                                                                          VkDevice                                       device,
133                                                                                                                                          const BinaryCollection&        programCollection,
134                                                                                                                                          const char*                            name,
135                                                                                                                                          VkShaderStageFlagBits          stage,
136                                                                                                                                          Move<VkShaderModule>*          module);
137         std::vector<Vertex4RGBA>        createQuad                                                      (const float size);
138
139 private:
140         tcu::TestStatus                         verifyImage                                                     (void);
141
142 private:
143         const tcu::IVec2                                                                m_renderSize;
144         const VkFormat                                                                  m_colorFormat;
145         const deUint32                                                                  m_rangeCount;
146         PushConstantData                                                                m_pushConstantRange[MAX_RANGE_COUNT];
147         const deBool                                                                    m_multipleUpdate;
148
149         VkImageCreateInfo                                                               m_colorImageCreateInfo;
150         Move<VkImage>                                                                   m_colorImage;
151         de::MovePtr<Allocation>                                                 m_colorImageAlloc;
152         Move<VkImageView>                                                               m_colorAttachmentView;
153         Move<VkRenderPass>                                                              m_renderPass;
154         Move<VkFramebuffer>                                                             m_framebuffer;
155
156         Move<VkShaderModule>                                                    m_vertexShaderModule;
157         Move<VkShaderModule>                                                    m_fragmentShaderModule;
158         Move<VkShaderModule>                                                    m_geometryShaderModule;
159         Move<VkShaderModule>                                                    m_tessControlShaderModule;
160         Move<VkShaderModule>                                                    m_tessEvaluationShaderModule;
161
162         VkShaderStageFlags                                                              m_shaderFlags;
163         std::vector<VkPipelineShaderStageCreateInfo>    m_shaderStage;
164
165         Move<VkBuffer>                                                                  m_vertexBuffer;
166         std::vector<Vertex4RGBA>                                                m_vertices;
167         de::MovePtr<Allocation>                                                 m_vertexBufferAlloc;
168
169         Move<VkBuffer>                                                                  m_uniformBuffer;
170         de::MovePtr<Allocation>                                                 m_uniformBufferAlloc;
171         Move<VkDescriptorPool>                                                  m_descriptorPool;
172         Move<VkDescriptorSetLayout>                                             m_descriptorSetLayout;
173         Move<VkDescriptorSet>                                                   m_descriptorSet;
174
175         Move<VkPipelineLayout>                                                  m_pipelineLayout;
176         Move<VkPipeline>                                                                m_graphicsPipelines;
177
178         Move<VkCommandPool>                                                             m_cmdPool;
179         Move<VkCommandBuffer>                                                   m_cmdBuffer;
180
181         Move<VkFence>                                                                   m_fence;
182 };
183
184 PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext&                   testContext,
185                                                                                                         const std::string&                      name,
186                                                                                                         const std::string&                      description,
187                                                                                                         const deUint32                          rangeCount,
188                                                                                                         const PushConstantData          pushConstantRange[MAX_RANGE_COUNT],
189                                                                                                         const deBool                            multipleUpdate)
190         : vkt::TestCase         (testContext, name, description)
191         , m_rangeCount          (rangeCount)
192         , m_multipleUpdate      (multipleUpdate)
193 {
194         deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
195 }
196
197 PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
198 {
199 }
200
201 TestInstance* PushConstantGraphicsTest::createInstance (Context& context) const
202 {
203         return new PushConstantGraphicsTestInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate);
204 }
205
206 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
207 {
208         switch (rangeSize)
209         {
210                 case 4:
211                         return SIZE_CASE_4;
212                 case 16:
213                         return SIZE_CASE_16;
214                 case 32:
215                         return SIZE_CASE_32;
216                 case 48:
217                         return SIZE_CASE_48;
218                 case 128:
219                         return SIZE_CASE_128;
220                 default:
221                         DE_FATAL("Range size unsupported yet");
222                         return SIZE_CASE_UNSUPPORTED;
223         }
224 }
225
226 void PushConstantGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
227 {
228         std::ostringstream      vertexSrc;
229         std::ostringstream      fragmentSrc;
230         std::ostringstream      geometrySrc;
231         std::ostringstream      tessControlSrc;
232         std::ostringstream      tessEvaluationSrc;
233
234         for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
235         {
236                 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
237                 {
238                         vertexSrc << "#version 450\n"
239                                           << "layout(location = 0) in highp vec4 position;\n"
240                                           << "layout(location = 1) in highp vec4 color;\n"
241                                           << "layout(location = 0) out highp vec4 vtxColor;\n"
242                                           << "layout(push_constant) uniform Material {\n";
243
244                         switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
245                         {
246                                 case SIZE_CASE_4:
247                                         vertexSrc << "int kind;\n"
248                                                           << "} matInst;\n";
249                                         break;
250                                 case SIZE_CASE_16:
251                                         vertexSrc << "vec4 color;\n"
252                                                           << "} matInst;\n"
253                                                           << "layout(location = 0) uniform UniformBuf {\n"
254                                                           << "vec4 element;\n"
255                                                           << "} uniformBuf;\n";
256                                         break;
257                                 case SIZE_CASE_32:
258                                         vertexSrc << "vec4 color[2];\n"
259                                                           << "} matInst;\n";
260                                         break;
261                                 case SIZE_CASE_48:
262                                         vertexSrc << "int dummy1;\n"
263                                                           << "vec4 dummy2;\n"
264                                                           << "vec4 color;\n"
265                                                           << "} matInst;\n";
266                                         break;
267                                 case SIZE_CASE_128:
268                                         vertexSrc << "vec4 color[8];\n"
269                                                           << "} matInst;\n";
270                                         break;
271                                 default:
272                                         DE_FATAL("Not implemented yet");
273                                         break;
274                         }
275
276                         vertexSrc << "void main()\n"
277                                           << "{\n"
278                                           << "  gl_Position = position;\n";
279
280                         switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
281                         {
282                                 case SIZE_CASE_4:
283                                         vertexSrc << "switch (matInst.kind) {\n"
284                                                           << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
285                                                           << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
286                                                           << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
287                                                           << "default: vtxColor = color; break;}\n"
288                                                           << "}\n";
289                                         break;
290                                 case SIZE_CASE_16:
291                                         vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
292                                                           << "}\n";
293                                         break;
294                                 case SIZE_CASE_32:
295                                         vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
296                                                           << "}\n";
297                                         break;
298                                 case SIZE_CASE_48:
299                                         vertexSrc << "vtxColor = matInst.color;\n"
300                                                           << "}\n";
301                                         break;
302                                 case SIZE_CASE_128:
303                                         vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
304                                                           << "for (int i = 0; i < 8; i++)\n"
305                                                           << "{\n"
306                                                           << "  color = color + matInst.color[i];\n"
307                                                           << "}\n"
308                                                           << "vtxColor = color * 0.125;\n"
309                                                           << "}\n";
310                                         break;
311                                 default:
312                                         DE_FATAL("Not implemented yet");
313                                         break;
314                         }
315
316                         sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
317                 }
318
319                 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
320                 {
321                         tessControlSrc << "#version 450\n"
322                                                    << "layout (vertices = 3) out;\n"
323                                                    << "layout(push_constant) uniform TessLevel {\n"
324                                                    << "    layout(offset = 24) int level;\n"
325                                                    << "} tessLevel;\n"
326                                                    << "layout(location = 0) in highp vec4 color[];\n"
327                                                    << "layout(location = 0) out highp vec4 vtxColor[];\n"
328                                                    << "void main()\n"
329                                                    << "{\n"
330                                                    << "  gl_TessLevelInner[0] = tessLevel.level;\n"
331                                                    << "  gl_TessLevelOuter[0] = tessLevel.level;\n"
332                                                    << "  gl_TessLevelOuter[1] = tessLevel.level;\n"
333                                                    << "  gl_TessLevelOuter[2] = tessLevel.level;\n"
334                                                    << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
335                                                    << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
336                                                    << "}\n";
337
338                         sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
339                 }
340
341                 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
342                 {
343                         tessEvaluationSrc << "#version 450\n"
344                                                           << "layout (triangles) in;\n"
345                                                           << "layout(push_constant) uniform Material {\n"
346                                                           << "    layout(offset = 32) vec4 color;\n"
347                                                           << "} matInst;\n"
348                                                           << "layout(location = 0) in highp vec4 color[];\n"
349                                                           << "layout(location = 0) out highp vec4 vtxColor;\n"
350                                                           << "void main()\n"
351                                                           << "{\n"
352                                                           << "  gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
353                                                           << "  vtxColor = matInst.color;\n"
354                                                           << "}\n";
355
356                         sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
357                 }
358
359                 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
360                 {
361                         geometrySrc << "#version 450\n"
362                                                 << "layout(triangles) in;\n"
363                                                 << "layout(triangle_strip, max_vertices=3) out;\n"
364                                                 << "layout(push_constant) uniform Material {\n"
365                                                 << "    layout(offset = 20) int kind;\n"
366                                                 << "} matInst;\n"
367                                                 << "layout(location = 0) in highp vec4 color[];\n"
368                                                 << "layout(location = 0) out highp vec4 vtxColor;\n"
369                                                 << "void main()\n"
370                                                 << "{\n"
371                                                 << "  for(int i=0; i<3; i++)\n"
372                                                 << "  {\n"
373                                                 << "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
374                                                 << "    gl_Position.w = gl_in[i].gl_Position.w;\n"
375                                                 << "    vtxColor = color[i];\n"
376                                                 << "    EmitVertex();\n"
377                                                 << "  }\n"
378                                                 << "  EndPrimitive();\n"
379                                                 << "}\n";
380
381                         sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
382                 }
383
384                 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
385                 {
386                         fragmentSrc << "#version 450\n"
387                                                 << "layout(location = 0) in highp vec4 vtxColor;\n"
388                                                 << "layout(location = 0) out highp vec4 fragColor;\n"
389                                                 << "layout(push_constant) uniform Material {\n";
390
391                         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
392                         {
393                                 fragmentSrc << "    layout(offset = 0) int kind;\n"
394                                                         << "} matInst;\n";
395                         }
396                         else
397                         {
398                                 fragmentSrc << "    layout(offset = 16) int kind;\n"
399                                                         << "} matInst;\n";
400                         }
401
402                         fragmentSrc << "void main (void)\n"
403                                                 << "{\n"
404                                                 << "    switch (matInst.kind) {\n"
405                                                 << "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
406                                                 << "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
407                                                 << "    case 2: fragColor = vtxColor; break;\n"
408                                                 << "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
409                                                 << "}\n";
410
411                         sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
412                 }
413         }
414
415         // add a pass through fragment shader if it's not activated in push constant ranges
416         if (fragmentSrc.str().empty())
417         {
418                 fragmentSrc << "#version 450\n"
419                                         << "layout(location = 0) in highp vec4 vtxColor;\n"
420                                         << "layout(location = 0) out highp vec4 fragColor;\n"
421                                         << "void main (void)\n"
422                                         << "{\n"
423                                         << "    fragColor = vtxColor;\n"
424                                         << "}\n";
425
426                 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
427         }
428 }
429
430 void PushConstantGraphicsTestInstance::createShaderStage (const DeviceInterface&        vk,
431                                                                                                                   VkDevice                                      device,
432                                                                                                                   const BinaryCollection&       programCollection,
433                                                                                                                   const char*                           name,
434                                                                                                                   VkShaderStageFlagBits         stage,
435                                                                                                                   Move<VkShaderModule>*         module)
436 {
437         *module = createShaderModule(vk, device, programCollection.get(name), 0);
438
439         const vk::VkPipelineShaderStageCreateInfo       stageCreateInfo =
440         {
441                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
442                 DE_NULL,                                                                                                // const void*                                                  pNext;
443                 0u,                                                                                                             // VkPipelineShaderStageCreateFlags             flags;
444                 stage,                                                                                                  // VkShaderStageFlagBits                                stage;
445                 **module,                                                                                               // VkShaderModule                                               module;
446                 "main",                                                                                                 // const char*                                                  pName;
447                 DE_NULL                                                                                                 // const VkSpecializationInfo*                  pSpecializationInfo;
448         };
449
450         m_shaderStage.push_back(stageCreateInfo);
451 }
452
453 std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
454 {
455         std::vector<Vertex4RGBA>        vertices;
456
457         const tcu::Vec4                         color                           = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
458         const Vertex4RGBA                       lowerLeftVertex         = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
459         const Vertex4RGBA                       lowerRightVertex        = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
460         const Vertex4RGBA                       UpperLeftVertex         = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
461         const Vertex4RGBA                       UpperRightVertex        = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
462
463         vertices.push_back(lowerLeftVertex);
464         vertices.push_back(lowerRightVertex);
465         vertices.push_back(UpperLeftVertex);
466         vertices.push_back(UpperLeftVertex);
467         vertices.push_back(lowerRightVertex);
468         vertices.push_back(UpperRightVertex);
469
470         return vertices;
471 }
472
473 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context&                                    context,
474                                                                                                                                         const deUint32                          rangeCount,
475                                                                                                                                         const PushConstantData          pushConstantRange[MAX_RANGE_COUNT],
476                                                                                                                                         deBool                                          multipleUpdate)
477         : vkt::TestInstance             (context)
478         , m_renderSize                  (32, 32)
479         , m_colorFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
480         , m_rangeCount                  (rangeCount)
481         , m_multipleUpdate              (multipleUpdate)
482         , m_shaderFlags                 (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
483 {
484         const DeviceInterface&          vk                                              = context.getDeviceInterface();
485         const VkDevice                          vkDevice                                = context.getDevice();
486         const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
487         SimpleAllocator                         memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
488         const VkComponentMapping        componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
489
490         deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
491
492         // Create color image
493         {
494                 const VkImageCreateInfo colorImageParams =
495                 {
496                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
497                         DE_NULL,                                                                                                                                        // const void*                          pNext;
498                         0u,                                                                                                                                                     // VkImageCreateFlags           flags;
499                         VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
500                         m_colorFormat,                                                                                                                          // VkFormat                                     format;
501                         { m_renderSize.x(), m_renderSize.y(), 1u },                                                                     // VkExtent3D                           extent;
502                         1u,                                                                                                                                                     // deUint32                                     mipLevels;
503                         1u,                                                                                                                                                     // deUint32                                     arrayLayers;
504                         VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlagBits        samples;
505                         VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
506                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
507                         VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
508                         1u,                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
509                         &queueFamilyIndex,                                                                                                                      // const deUint32*                      pQueueFamilyIndices;
510                         VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
511                 };
512
513                 m_colorImageCreateInfo  = colorImageParams;
514                 m_colorImage                    = createImage(vk, vkDevice, &m_colorImageCreateInfo);
515
516                 // Allocate and bind color image memory
517                 m_colorImageAlloc               = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
518                 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
519         }
520
521         // Create color attachment view
522         {
523                 const VkImageViewCreateInfo colorAttachmentViewParams =
524                 {
525                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                              sType;
526                         DE_NULL,                                                                                        // const void*                                  pNext;
527                         0u,                                                                                                     // VkImageViewCreateFlags               flags;
528                         *m_colorImage,                                                                          // VkImage                                              image;
529                         VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                              viewType;
530                         m_colorFormat,                                                                          // VkFormat                                             format;
531                         componentMappingRGBA,                                                           // VkChannelMapping                             channels;
532                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },          // VkImageSubresourceRange              subresourceRange;
533                 };
534
535                 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
536         }
537
538         // Create render pass
539         {
540                 const VkAttachmentDescription colorAttachmentDescription =
541                 {
542                         0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
543                         m_colorFormat,                                                                          // VkFormat                                                     format;
544                         VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
545                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
546                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
547                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
548                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
549                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
550                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
551                 };
552
553                 const VkAttachmentDescription attachments[1] =
554                 {
555                         colorAttachmentDescription
556                 };
557
558                 const VkAttachmentReference colorAttachmentReference =
559                 {
560                         0u,                                                                                                     // deUint32                     attachment;
561                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
562                 };
563
564                 const VkAttachmentReference depthAttachmentReference =
565                 {
566                         VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
567                         VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
568                 };
569
570                 const VkSubpassDescription subpassDescription =
571                 {
572                         0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
573                         VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
574                         0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
575                         DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
576                         1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
577                         &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
578                         DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
579                         &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
580                         0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
581                         DE_NULL                                                                                         // const VkAttachmentReference*         pPreserveAttachments;
582                 };
583
584                 const VkRenderPassCreateInfo renderPassParams =
585                 {
586                         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
587                         DE_NULL,                                                                                        // const void*                                          pNext;
588                         0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
589                         1u,                                                                                                     // deUint32                                                     attachmentCount;
590                         attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
591                         1u,                                                                                                     // deUint32                                                     subpassCount;
592                         &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
593                         0u,                                                                                                     // deUint32                                                     dependencyCount;
594                         DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
595                 };
596
597                 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
598         }
599
600         // Create framebuffer
601         {
602                 const VkImageView attachmentBindInfos[1] =
603                 {
604                   *m_colorAttachmentView
605                 };
606
607                 const VkFramebufferCreateInfo framebufferParams =
608                 {
609                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                              sType;
610                         DE_NULL,                                                                                        // const void*                                  pNext;
611                         0u,                                                                                                     // VkFramebufferCreateFlags             flags;
612                         *m_renderPass,                                                                          // VkRenderPass                                 renderPass;
613                         1u,                                                                                                     // deUint32                                             attachmentCount;
614                         attachmentBindInfos,                                                            // const VkImageView*                   pAttachments;
615                         (deUint32)m_renderSize.x(),                                                     // deUint32                                             width;
616                         (deUint32)m_renderSize.y(),                                                     // deUint32                                             height;
617                         1u                                                                                                      // deUint32                                             layers;
618                 };
619
620                 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
621         }
622
623         // Create pipeline layout
624         {
625                 // create push constant range
626                 VkPushConstantRange     pushConstantRanges[MAX_RANGE_COUNT];
627                 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
628                 {
629                         pushConstantRanges[rangeNdx].stageFlags = m_pushConstantRange[rangeNdx].range.shaderStage;
630                         pushConstantRanges[rangeNdx].offset             = m_pushConstantRange[rangeNdx].range.offset;
631                         pushConstantRanges[rangeNdx].size               = m_pushConstantRange[rangeNdx].range.size;
632                 }
633
634                 // create descriptor set layout
635                 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
636
637                 // create descriptor pool
638                 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
639
640                 // create uniform buffer
641                 const VkBufferCreateInfo uniformBufferCreateInfo =
642                 {
643                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
644                         DE_NULL,                                                                                                        // const void*                  pNext;
645                         0u,                                                                                                                     // VkBufferCreateFlags  flags
646                         16u,                                                                                                            // VkDeviceSize                 size;
647                         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                                                     // VkBufferUsageFlags   usage;
648                         VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
649                         1u,                                                                                                                     // deUint32                             queueFamilyCount;
650                         &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
651                 };
652
653                 m_uniformBuffer                 = createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
654                 m_uniformBufferAlloc    = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
655                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
656
657                 tcu::Vec4       value   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
658                 deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
659                 flushMappedMemoryRange(vk, vkDevice, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset(), 16u);
660
661                 // create and update descriptor set
662                 const VkDescriptorSetAllocateInfo allocInfo =
663                 {
664                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                         // VkStructureType                             sType;
665                         DE_NULL,                                                                                                        // const void*                                 pNext;
666                         *m_descriptorPool,                                                                                      // VkDescriptorPool                            descriptorPool;
667                         1u,                                                                                                                     // uint32_t                                    setLayoutCount;
668                         &(*m_descriptorSetLayout),                                                                      // const VkDescriptorSetLayout*                pSetLayouts;
669                 };
670                 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
671
672                 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
673
674                 DescriptorSetUpdateBuilder()
675                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
676                         .update(vk, vkDevice);
677
678                 // create pipeline layout
679                 const VkPipelineLayoutCreateInfo        pipelineLayoutParams    =
680                 {
681                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
682                         DE_NULL,                                                                                        // const void*                                  pNext;
683                         0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
684                         1u,                                                                                                     // deUint32                                             descriptorSetCount;
685                         &(*m_descriptorSetLayout),                                                      // const VkDescriptorSetLayout* pSetLayouts;
686                         m_rangeCount,                                                                           // deUint32                                             pushConstantRangeCount;
687                         pushConstantRanges                                                                      // const VkPushConstantRange*   pPushConstantRanges;
688                 };
689
690                 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
691         }
692
693         // Create shaders
694         {
695                 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
696                 {
697                         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
698                         {
699                                 m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
700                         }
701                         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
702                         {
703                                 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
704                         }
705                         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
706                         {
707                                 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
708                         }
709                 }
710
711                 VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
712
713                 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", VK_SHADER_STAGE_VERTEX_BIT , &m_vertexShaderModule);
714                 if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
715                 {
716                         if (features.tessellationShader == VK_FALSE)
717                         {
718                                 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
719                         }
720                         createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessControlShaderModule);
721                         createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvaluationShaderModule);
722                 }
723                 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
724                 {
725                         if (features.geometryShader == VK_FALSE)
726                         {
727                                 TCU_THROW(NotSupportedError, "Geometry Not Supported");
728                         }
729                         createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
730                 }
731                 createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
732         }
733
734         // Create pipeline
735         {
736                 const VkVertexInputBindingDescription vertexInputBindingDescription =
737                 {
738                         0u,                                                                             // deUint32                                     binding;
739                         sizeof(Vertex4RGBA),                                    // deUint32                                     strideInBytes;
740                         VK_VERTEX_INPUT_RATE_VERTEX                             // VkVertexInputStepRate        stepRate;
741                 };
742
743                 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
744                 {
745                         {
746                                 0u,                                                                     // deUint32     location;
747                                 0u,                                                                     // deUint32     binding;
748                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
749                                 0u                                                                      // deUint32     offsetInBytes;
750                         },
751                         {
752                                 1u,                                                                     // deUint32     location;
753                                 0u,                                                                     // deUint32     binding;
754                                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
755                                 DE_OFFSET_OF(Vertex4RGBA, color),       // deUint32     offset;
756                         }
757                 };
758
759                 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
760                 {
761                         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
762                         DE_NULL,                                                                                                                // const void*                                                          pNext;
763                         0u,                                                                                                                             // vkPipelineVertexInputStateCreateFlags        flags;
764                         1u,                                                                                                                             // deUint32                                                                     bindingCount;
765                         &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
766                         2u,                                                                                                                             // deUint32                                                                     attributeCount;
767                         vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
768                 };
769
770                 const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
771                 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
772                 {
773                         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
774                         DE_NULL,                                                                                                                // const void*                                                          pNext;
775                         (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags      flags;
776                         topology,                                                                                                               // VkPrimitiveTopology                                          topology;
777                         false                                                                                                                   // VkBool32                                                                     primitiveRestartEnable;
778                 };
779
780                 const VkViewport viewport =
781                 {
782                         0.0f,                                           // float        originX;
783                         0.0f,                                           // float        originY;
784                         (float)m_renderSize.x(),        // float        width;
785                         (float)m_renderSize.y(),        // float        height;
786                         0.0f,                                           // float        minDepth;
787                         1.0f                                            // float        maxDepth;
788                 };
789
790                 const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
791
792                 const VkPipelineViewportStateCreateInfo viewportStateParams =
793                 {
794                         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
795                         DE_NULL,                                                                                                                // const void*                                                  pNext;
796                         (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags   flags;
797                         1u,                                                                                                                             // deUint32                                                             viewportCount;
798                         &viewport,                                                                                                              // const VkViewport*                                    pViewports;
799                         1u,                                                                                                                             // deUint32                                                             scissorCount;
800                         &scissor,                                                                                                               // const VkRect2D*                                              pScissors;
801                 };
802
803                 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
804                 {
805                         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
806                         DE_NULL,                                                                                                                // const void*                                                          pNext;
807                         0u,                                                                                                                             // VkPipelineRasterizationStateCreateFlags      flags;
808                         false,                                                                                                                  // VkBool32                                                                     depthClampEnable;
809                         false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
810                         VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
811                         VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
812                         VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
813                         VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
814                         0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
815                         0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
816                         0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
817                         1.0f,                                                                                                                   // float                                                                        lineWidth;
818                 };
819
820                 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
821                 {
822                         false,                                                                                                                  // VkBool32                                     blendEnable;
823                         VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcColorBlendFactor;
824                         VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstColorBlendFactor;
825                         VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
826                         VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcAlphaBlendFactor;
827                         VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstAlphaBlendFactor;
828                         VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
829                         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |                   // VkColorComponentFlags        colorWriteMask;
830                                 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
831                 };
832
833                 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
834                 {
835                         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
836                         DE_NULL,                                                                                                        // const void*                                                                  pNext;
837                         0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
838                         false,                                                                                                          // VkBool32                                                                             logicOpEnable;
839                         VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
840                         1u,                                                                                                                     // deUint32                                                                             attachmentCount;
841                         &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
842                         { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
843                 };
844
845                 const VkPipelineMultisampleStateCreateInfo      multisampleStateParams  =
846                 {
847                         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
848                         DE_NULL,                                                                                                        // const void*                                                          pNext;
849                         0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
850                         VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
851                         false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
852                         0.0f,                                                                                                           // float                                                                        minSampleShading;
853                         DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
854                         false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
855                         false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
856                 };
857
858                 const VkPipelineDynamicStateCreateInfo dynamicStateParams               =
859                 {
860                         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,           // VkStructureType                                              sType;
861                         DE_NULL,                                                                                                        // const void*                                                  pNext;
862                         0u,                                                                                                                     // VkPipelineDynamicStateCreateFlags    flags;
863                         0u,                                                                                                                     // deUint32                                                             dynamicStateCount;
864                         DE_NULL                                                                                                         // const VkDynamicState*                                pDynamicStates;
865                 };
866
867                 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
868                 {
869                         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
870                         DE_NULL,                                                                                                        // const void*                                                          pNext;
871                         0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags       flags;
872                         false,                                                                                                          // VkBool32                                                                     depthTestEnable;
873                         false,                                                                                                          // VkBool32                                                                     depthWriteEnable;
874                         VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
875                         false,                                                                                                          // VkBool32                                                                     depthBoundsTestEnable;
876                         false,                                                                                                          // VkBool32                                                                     stencilTestEnable;
877                         // VkStencilOpState     front;
878                         {
879                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilFailOp;
880                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilPassOp;
881                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilDepthFailOp;
882                                 VK_COMPARE_OP_NEVER,    // VkCompareOp  stencilCompareOp;
883                                 0u,                                             // deUint32             stencilCompareMask;
884                                 0u,                                             // deUint32             stencilWriteMask;
885                                 0u,                                             // deUint32             stencilReference;
886                         },
887                         // VkStencilOpState     back;
888                         {
889                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilFailOp;
890                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilPassOp;
891                                 VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilDepthFailOp;
892                                 VK_COMPARE_OP_NEVER,    // VkCompareOp  stencilCompareOp;
893                                 0u,                                             // deUint32             stencilCompareMask;
894                                 0u,                                             // deUint32             stencilWriteMask;
895                                 0u,                                             // deUint32             stencilReference;
896                         },
897                         -1.0f,                                                                                                          // float                        minDepthBounds;
898                         +1.0f,                                                                                                          // float                        maxDepthBounds;
899                 };
900
901                 const VkPipelineTessellationStateCreateInfo tessellationStateParams =
902                 {
903                         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
904                         DE_NULL,                                                                                                                // const void*                                 pNext;
905                         0u,                                                                                                                             // VkPipelineTesselationStateCreateFlags       flags;
906                         3u,                                                                                                                             // uint32_t                                    patchControlPoints;
907                 };
908
909                 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
910                 {
911                         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
912                         DE_NULL,                                                                                        // const void*                                                                          pNext;
913                         0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
914                         (deUint32)m_shaderStage.size(),                                         // deUint32                                                                                     stageCount;
915                         &m_shaderStage[0],                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
916                         &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
917                         &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
918                         (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &tessellationStateParams: DE_NULL),                 // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
919                         &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
920                         &rasterStateParams,                                                                     // const VkPipelineRasterStateCreateInfo*                       pRasterState;
921                         &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
922                         &depthStencilStateParams,                                                       // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
923                         &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
924                         &dynamicStateParams,                                                            // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
925                         *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
926                         *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
927                         0u,                                                                                                     // deUint32                                                                                     subpass;
928                         0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
929                         0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
930                 };
931
932                 m_graphicsPipelines = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
933         }
934
935         // Create vertex buffer
936         {
937                 m_vertices                      = createQuad(1.0f);
938
939                 const VkBufferCreateInfo vertexBufferParams =
940                 {
941                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
942                         DE_NULL,                                                                                                        // const void*                  pNext;
943                         0u,                                                                                                                     // VkBufferCreateFlags  flags;
944                         (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),        // VkDeviceSize                 size;
945                         VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                                                      // VkBufferUsageFlags   usage;
946                         VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
947                         1u,                                                                                                                     // deUint32                             queueFamilyCount;
948                         &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
949                 };
950
951                 m_vertexBuffer          = createBuffer(vk, vkDevice, &vertexBufferParams);
952                 m_vertexBufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
953
954                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
955
956                 // Load vertices into vertex buffer
957                 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
958                 flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
959         }
960
961         // Create command pool
962         {
963                 const VkCommandPoolCreateInfo cmdPoolParams =
964                 {
965                         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,     // VkStructureType              sType;
966                         DE_NULL,                                                                        // const void*                  pNext;
967                         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,           // VkCmdPoolCreateFlags flags;
968                         queueFamilyIndex                                                        // deUint32                             queueFamilyIndex;
969                 };
970                 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
971         }
972
973         // Create command buffer
974         {
975                 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
976                 {
977                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
978                         DE_NULL,                                                                                // const void*                          pNext;
979                         *m_cmdPool,                                                                             // VkCommandPool                        commandPool;
980                         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel         level;
981                         1u                                                                                              // deUint32                                     bufferCount;
982                 };
983
984                 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
985                 {
986                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
987                         DE_NULL,                                                                                // const void*                                          pNext;
988                         0u,                                                                                             // VkCommandBufferUsageFlags            flags;
989                         DE_NULL,                                                                                // VkRenderPass                                         renderPass;
990                         0u,                                                                                             // deUint32                                                     subpass;
991                         DE_NULL,                                                                                // VkFramebuffer                                        framebuffer;
992                         false,                                                                                  // VkBool32                                                     occlusionQueryEnable;
993                         0u,                                                                                             // VkQueryControlFlags                          queryFlags;
994                         0u                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics;
995                 };
996
997                 const VkClearValue attachmentClearValues[] =
998                 {
999                         defaultClearValue(m_colorFormat)
1000                 };
1001
1002                 const VkRenderPassBeginInfo renderPassBeginInfo =
1003                 {
1004                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
1005                         DE_NULL,                                                                                                // const void*                  pNext;
1006                         *m_renderPass,                                                                                  // VkRenderPass                 renderPass;
1007                         *m_framebuffer,                                                                                 // VkFramebuffer                framebuffer;
1008                         { { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } },  // VkRect2D                             renderArea;
1009                         1,                                                                                                              // deUint32                             clearValueCount;
1010                         attachmentClearValues                                                                   // const VkClearValue*  pClearValues;
1011                 };
1012
1013                 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1014
1015                 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1016                 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1017
1018                 // update push constant
1019                 std::vector<tcu::Vec4> color(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1020                 std::vector<tcu::Vec4> allOnes(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1021
1022                 const deUint32  kind    = 2u;
1023                 const void*             value   = DE_NULL;
1024                 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1025                 {
1026                         value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
1027
1028                         vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
1029
1030                         if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1031                         {
1032                                 value = (void*)(&allOnes[0]);
1033                                 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
1034                         }
1035                 }
1036
1037                 // draw quad
1038                 const VkDeviceSize      triangleOffset  = (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
1039                 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1040                 {
1041                         VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
1042
1043                         if (m_multipleUpdate)
1044                         {
1045                                 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
1046                         }
1047
1048                         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
1049                         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1050                         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1051
1052                         vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
1053                 }
1054
1055                 vk.cmdEndRenderPass(*m_cmdBuffer);
1056                 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1057         }
1058
1059         // Create fence
1060         {
1061                 const VkFenceCreateInfo fenceParams =
1062                 {
1063                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
1064                         DE_NULL,                                                                // const void*                  pNext;
1065                         0u                                                                              // VkFenceCreateFlags   flags;
1066                 };
1067
1068                 m_fence = createFence(vk, vkDevice, &fenceParams);
1069         }
1070 }
1071
1072 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
1073 {
1074 }
1075
1076 tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
1077 {
1078         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1079         const VkDevice                          vkDevice        = m_context.getDevice();
1080         const VkQueue                           queue           = m_context.getUniversalQueue();
1081         const VkSubmitInfo                      submitInfo      =
1082         {
1083                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
1084                 DE_NULL,                                                // const void*                          pNext;
1085                 0u,                                                             // deUint32                                     waitSemaphoreCount;
1086                 DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
1087                 1u,                                                             // deUint32                                     commandBufferCount;
1088                 &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
1089                 0u,                                                             // deUint32                                     signalSemaphoreCount;
1090                 DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
1091         };
1092
1093         VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1094         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1095         VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1096
1097         return verifyImage();
1098 }
1099
1100 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
1101 {
1102         const tcu::TextureFormat        tcuColorFormat  = mapVkFormat(m_colorFormat);
1103         const tcu::TextureFormat        tcuDepthFormat  = tcu::TextureFormat();
1104         const ColorVertexShader         vertexShader;
1105         const ColorFragmentShader       fragmentShader  (tcuColorFormat, tcuDepthFormat);
1106         const rr::Program                       program                 (&vertexShader, &fragmentShader);
1107         ReferenceRenderer                       refRenderer             (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
1108         bool                                            compareOk               = false;
1109
1110         // Render reference image
1111         {
1112                 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
1113                 {
1114                         m_vertices = createQuad(0.5f);
1115                 }
1116
1117                 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1118                 {
1119                         if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
1120                         {
1121                                 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1122                                 {
1123                                         m_vertices[vertexNdx].color.xyzw() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1124                                 }
1125                         }
1126                 }
1127
1128                 if (m_multipleUpdate)
1129                 {
1130                         for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
1131                         {
1132                                 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
1133                         }
1134                         for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
1135                         {
1136                                 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
1137                         }
1138                 }
1139
1140                 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
1141                 {
1142                         rr::RenderState renderState(refRenderer.getViewportState());
1143
1144                         refRenderer.draw(renderState,
1145                                                          rr::PRIMITIVETYPE_TRIANGLES,
1146                                                          std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
1147                                                                                                           m_vertices.begin() + (triangleNdx + 1) * 3));
1148                 }
1149         }
1150
1151         // Compare result with reference image
1152         {
1153                 const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
1154                 const VkDevice                                  vkDevice                        = m_context.getDevice();
1155                 const VkQueue                                   queue                           = m_context.getUniversalQueue();
1156                 const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1157                 SimpleAllocator                                 allocator                       (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1158                 de::MovePtr<tcu::TextureLevel>  result                          = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
1159
1160                 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1161                                                                                                                           "IntImageCompare",
1162                                                                                                                           "Image comparison",
1163                                                                                                                           refRenderer.getAccess(),
1164                                                                                                                           result->getAccess(),
1165                                                                                                                           tcu::UVec4(2, 2, 2, 2),
1166                                                                                                                           tcu::IVec3(1, 1, 0),
1167                                                                                                                           true,
1168                                                                                                                           tcu::COMPARE_LOG_RESULT);
1169         }
1170
1171         if (compareOk)
1172                 return tcu::TestStatus::pass("Result image matches reference");
1173         else
1174                 return tcu::TestStatus::fail("Image mismatch");
1175 }
1176
1177 class PushConstantComputeTest : public vkt::TestCase
1178 {
1179 public:
1180                                                         PushConstantComputeTest         (tcu::TestContext&              testContext,
1181                                                                                                                  const std::string&             name,
1182                                                                                                                  const std::string&             description,
1183                                                                                                                  const PushConstantData pushConstantRange);
1184         virtual                                 ~PushConstantComputeTest        (void);
1185         virtual void                    initPrograms                            (SourceCollections& sourceCollections) const;
1186         virtual TestInstance*   createInstance                          (Context& context) const;
1187
1188 private:
1189         const PushConstantData  m_pushConstantRange;
1190 };
1191
1192 class PushConstantComputeTestInstance : public vkt::TestInstance
1193 {
1194 public:
1195                                                         PushConstantComputeTestInstance         (Context&                               context,
1196                                                                                                                                  const PushConstantData pushConstantRange);
1197         virtual                                 ~PushConstantComputeTestInstance        (void);
1198         virtual tcu::TestStatus iterate                                                         (void);
1199
1200 private:
1201         const PushConstantData                  m_pushConstantRange;
1202
1203         Move<VkBuffer>                                  m_outBuffer;
1204         de::MovePtr<Allocation>                 m_outBufferAlloc;
1205         Move<VkDescriptorPool>                  m_descriptorPool;
1206         Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
1207         Move<VkDescriptorSet>                   m_descriptorSet;
1208
1209         Move<VkPipelineLayout>                  m_pipelineLayout;
1210         Move<VkPipeline>                                m_computePipelines;
1211
1212         Move<VkShaderModule>                    m_computeShaderModule;
1213
1214         Move<VkCommandPool>                             m_cmdPool;
1215         Move<VkCommandBuffer>                   m_cmdBuffer;
1216
1217         Move<VkFence>                                   m_fence;
1218 };
1219
1220 PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext&                     testContext,
1221                                                                                                   const std::string&            name,
1222                                                                                                   const std::string&            description,
1223                                                                                                   const PushConstantData        pushConstantRange)
1224         : vkt::TestCase                 (testContext, name, description)
1225         , m_pushConstantRange   (pushConstantRange)
1226 {
1227 }
1228
1229 PushConstantComputeTest::~PushConstantComputeTest (void)
1230 {
1231 }
1232
1233 TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1234 {
1235         return new PushConstantComputeTestInstance(context, m_pushConstantRange);
1236 }
1237
1238 void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1239 {
1240         std::ostringstream      computeSrc;
1241
1242         computeSrc << "#version 450\n"
1243                            << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1244                            << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1245                            << "  vec4 elements[];\n"
1246                            << "} outData;\n"
1247                            << "layout(push_constant) uniform Material{\n"
1248                            << "  vec4 element;\n"
1249                            << "} matInst;\n"
1250                            << "void main (void)\n"
1251                            << "{\n"
1252                            << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1253                            << "}\n";
1254
1255         sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1256 }
1257
1258 PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context&                                      context,
1259                                                                                                                                   const PushConstantData        pushConstantRange)
1260         : vkt::TestInstance             (context)
1261         , m_pushConstantRange   (pushConstantRange)
1262 {
1263         const DeviceInterface&          vk                                      = context.getDeviceInterface();
1264         const VkDevice                          vkDevice                        = context.getDevice();
1265         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
1266         SimpleAllocator                         memAlloc                        (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1267
1268         // Create pipeline layout
1269         {
1270                 // create push constant range
1271                 VkPushConstantRange     pushConstantRanges;
1272                 pushConstantRanges.stageFlags   = m_pushConstantRange.range.shaderStage;
1273                 pushConstantRanges.offset               = m_pushConstantRange.range.offset;
1274                 pushConstantRanges.size                 = m_pushConstantRange.range.size;
1275
1276                 // create descriptor set layout
1277                 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1278
1279                 // create descriptor pool
1280                 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1281
1282                 // create uniform buffer
1283                 const VkDeviceSize                      bufferSize                      = sizeof(tcu::Vec4) * 8;
1284                 const VkBufferCreateInfo        bufferCreateInfo        =
1285                 {
1286                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
1287                         DE_NULL,                                                                                                        // const void*                  pNext;
1288                         0u,                                                                                                                     // VkBufferCreateFlags  flags
1289                         bufferSize,                                                                                                     // VkDeviceSize                 size;
1290                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,                                                     // VkBufferUsageFlags   usage;
1291                         VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
1292                         1u,                                                                                                                     // deUint32                             queueFamilyCount;
1293                         &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
1294                 };
1295
1296                 m_outBuffer                     = createBuffer(vk, vkDevice, &bufferCreateInfo);
1297                 m_outBufferAlloc        = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1298                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1299
1300                 // create and update descriptor set
1301                 const VkDescriptorSetAllocateInfo allocInfo =
1302                 {
1303                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                         // VkStructureType                             sType;
1304                         DE_NULL,                                                                                                        // const void*                                 pNext;
1305                         *m_descriptorPool,                                                                                      // VkDescriptorPool                            descriptorPool;
1306                         1u,                                                                                                                     // uint32_t                                    setLayoutCount;
1307                         &(*m_descriptorSetLayout),                                                                      // const VkDescriptorSetLayout*                pSetLayouts;
1308                 };
1309                 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1310
1311                 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1312
1313                 DescriptorSetUpdateBuilder()
1314                         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1315                         .update(vk, vkDevice);
1316
1317                 // create pipeline layout
1318                 const VkPipelineLayoutCreateInfo        pipelineLayoutParams    =
1319                 {
1320                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
1321                         DE_NULL,                                                                                        // const void*                                  pNext;
1322                         0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
1323                         1u,                                                                                                     // deUint32                                             descriptorSetCount;
1324                         &(*m_descriptorSetLayout),                                                      // const VkDescriptorSetLayout* pSetLayouts;
1325                         1u,                                                                                                     // deUint32                                             pushConstantRangeCount;
1326                         &pushConstantRanges                                                                     // const VkPushConstantRange*   pPushConstantRanges;
1327                 };
1328
1329                 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1330         }
1331
1332         // create pipeline
1333         {
1334                 m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1335
1336                 const VkPipelineShaderStageCreateInfo   stageCreateInfo =
1337                 {
1338                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
1339                         DE_NULL,                                                                                                // const void*                                                  pNext;
1340                         0u,                                                                                                             // VkPipelineShaderStageCreateFlags             flags;
1341                         VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                                stage;
1342                         *m_computeShaderModule,                                                                 // VkShaderModule                                               module;
1343                         "main",                                                                                                 // const char*                                                  pName;
1344                         DE_NULL                                                                                                 // const VkSpecializationInfo*                  pSpecializationInfo;
1345                 };
1346
1347                 const VkComputePipelineCreateInfo               createInfo      =
1348                 {
1349                         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // VkStructureType                             sType;
1350                         DE_NULL,                                                                                                // const void*                                 pNext;
1351                         0u,                                                                                                             // VkPipelineCreateFlags                       flags;
1352                         stageCreateInfo,                                                                                // VkPipelineShaderStageCreateInfo             stage;
1353                         *m_pipelineLayout,                                                                              // VkPipelineLayout                            layout;
1354                         (VkPipeline)0,                                                                                  // VkPipeline                                  basePipelineHandle;
1355                         0u,                                                                                                             // int32_t                                     basePipelineIndex;
1356                 };
1357
1358                 m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1359         }
1360
1361         // Create command pool
1362         {
1363                 const VkCommandPoolCreateInfo cmdPoolParams =
1364                 {
1365                         VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,             // VkStructureType              sType;
1366                         DE_NULL,                                                                                // const void*                  pNext;
1367                         VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,                   // VkCmdPoolCreateFlags flags;
1368                         queueFamilyIndex                                                                // deUint32                             queueFamilyIndex;
1369                 };
1370                 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
1371         }
1372
1373         // Create command buffer
1374         {
1375                 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
1376                 {
1377                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
1378                         DE_NULL,                                                                                // const void*                          pNext;
1379                         *m_cmdPool,                                                                             // VkCommandPool                        commandPool;
1380                         VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel         level;
1381                         1u                                                                                              // deUint32                                     bufferCount;
1382                 };
1383
1384                 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
1385
1386                 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1387                 {
1388                         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
1389                         DE_NULL,                                                                                // const void*                                          pNext;
1390                         0u,                                                                                             // VkCommandBufferUsageFlags            flags;
1391                         DE_NULL,                                                                                // VkRenderPass                                         renderPass;
1392                         0u,                                                                                             // deUint32                                                     subpass;
1393                         DE_NULL,                                                                                // VkFramebuffer                                        framebuffer;
1394                         false,                                                                                  // VkBool32                                                     occlusionQueryEnable;
1395                         0u,                                                                                             // VkQueryControlFlags                          queryFlags;
1396                         0u                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics;
1397                 };
1398
1399                 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1400
1401                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1402                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1403
1404                 // update push constant
1405                 tcu::Vec4       value   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1406                 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1407
1408                 vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1409
1410                 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1411         }
1412
1413         // Create fence
1414         {
1415                 const VkFenceCreateInfo fenceParams =
1416                 {
1417                         VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
1418                         DE_NULL,                                                                // const void*                  pNext;
1419                         0u                                                                              // VkFenceCreateFlags   flags;
1420                 };
1421
1422                 m_fence = createFence(vk, vkDevice, &fenceParams);
1423         }
1424 }
1425
1426 PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1427 {
1428 }
1429
1430 tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1431 {
1432         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
1433         const VkDevice                          vkDevice        = m_context.getDevice();
1434         const VkQueue                           queue           = m_context.getUniversalQueue();
1435         const VkSubmitInfo                      submitInfo      =
1436         {
1437                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
1438                 DE_NULL,                                                // const void*                          pNext;
1439                 0u,                                                             // deUint32                                     waitSemaphoreCount;
1440                 DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
1441                 1u,                                                             // deUint32                                     commandBufferCount;
1442                 &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
1443                 0u,                                                             // deUint32                                     signalSemaphoreCount;
1444                 DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
1445         };
1446
1447         VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
1448         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
1449         VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
1450
1451         // verify result
1452         std::vector<tcu::Vec4>  expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1453         if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1454         {
1455                 return tcu::TestStatus::fail("Image mismatch");
1456         }
1457         return tcu::TestStatus::pass("result image matches with reference");
1458 }
1459
1460 } // anonymous
1461
1462 tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
1463 {
1464         static const struct
1465         {
1466                 const char*                     name;
1467                 const char*                     description;
1468                 deUint32                        count;
1469                 PushConstantData        range[MAX_RANGE_COUNT];
1470                 deBool                          hasMultipleUpdates;
1471         } graphicsParams[] =
1472         {
1473                 // test range size from minimum valid size to maximum
1474                 {
1475                         "range_size_4",
1476                         "test range size is 4 bytes(minimum valid size)",
1477                         1u,
1478                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
1479                         false
1480                 },
1481                 {
1482                         "range_size_16",
1483                         "test range size is 16 bytes, and together with a normal uniform",
1484                         1u,
1485                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
1486                         false
1487                 },
1488                 {
1489                         "range_size_128",
1490                         "test range size is 128 bytes(maximum valid size)",
1491                         1u,
1492                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
1493                         false
1494                 },
1495                 // test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
1496                 {
1497                         "count_2_shader_VF",
1498                         "test range count is 2, use vertex and fragment shaders",
1499                         2u,
1500                         {
1501                                 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1502                                 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1503                         },
1504                         false
1505                 },
1506                 {
1507                         "count_3shader_VGF",
1508                         "test range count is 3, use vertex, geometry and fragment shaders",
1509                         3u,
1510                         {
1511                                 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1512                                 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1513                                 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1514                         },
1515                         false
1516                 },
1517                 {
1518                         "count_5_shader_VTGF",
1519                         "test range count is 5, use vertex, tessellation, geometry and fragment shaders",
1520                         5u,
1521                         {
1522                                 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1523                                 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1524                                 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1525                                 { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
1526                                 { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
1527                         },
1528                         false
1529                 },
1530                 {
1531                         "count_1_shader_VF",
1532                         "test range count is 1, vertex and fragment shaders share one range",
1533                         1u,
1534                         { { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
1535                         false
1536                 },
1537                 // test data partial update and multiple times update
1538                 {
1539                         "data_update_partial_1",
1540                         "test partial update of the values",
1541                         1u,
1542                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
1543                         false
1544                 },
1545                 {
1546                         "data_update_partial_2",
1547                         "test partial update of the values",
1548                         1u,
1549                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
1550                         false
1551                 },
1552                 {
1553                         "data_update_multiple",
1554                         "test multiple times update of the values",
1555                         1u,
1556                         { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
1557                         true
1558                 },
1559         };
1560
1561         static const struct
1562         {
1563                 const char*                     name;
1564                 const char*                     description;
1565                 PushConstantData        range;
1566         } computeParams[] =
1567         {
1568                 {
1569                         "simple_test",
1570                         "test compute pipeline",
1571                         { { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
1572                 },
1573         };
1574
1575         de::MovePtr<tcu::TestCaseGroup> pushConstantTests       (new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
1576
1577         de::MovePtr<tcu::TestCaseGroup> graphicsTests   (new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
1578         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
1579         {
1580                 graphicsTests->addChild(new PushConstantGraphicsTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates));
1581         }
1582         pushConstantTests->addChild(graphicsTests.release());
1583
1584         de::MovePtr<tcu::TestCaseGroup> computeTests    (new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
1585         computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
1586         pushConstantTests->addChild(computeTests.release());
1587
1588         return pushConstantTests.release();
1589 }
1590
1591 } // pipeline
1592 } // vkt