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