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