xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelinePushConstantTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Limited.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief PushConstant Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelinePushConstantTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 
33 #include "vktTestCase.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkTypeUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkImageWithMemory.hpp"
45 #include "vkBufferWithMemory.hpp"
46 #include "vkBarrierUtil.hpp"
47 
48 #include "tcuImageCompare.hpp"
49 #include "tcuTestLog.hpp"
50 
51 #include "deMemory.h"
52 #include "deRandom.hpp"
53 #include "deStringUtil.hpp"
54 #include "deUniquePtr.hpp"
55 
56 #include <algorithm>
57 #include <sstream>
58 #include <vector>
59 
60 namespace vkt
61 {
62 namespace pipeline
63 {
64 
65 using namespace vk;
66 
67 namespace
68 {
69 
70 enum
71 {
72     TRIANGLE_COUNT  = 2,
73     MAX_RANGE_COUNT = 5
74 };
75 
76 enum RangeSizeCase
77 {
78     SIZE_CASE_4 = 0,
79     SIZE_CASE_8,
80     SIZE_CASE_12,
81     SIZE_CASE_16,
82     SIZE_CASE_32,
83     SIZE_CASE_36,
84     SIZE_CASE_48,
85     SIZE_CASE_128,
86     SIZE_CASE_UNSUPPORTED
87 };
88 
89 enum CommandType
90 {
91     CMD_BIND_PIPELINE_GRAPHICS = 0,
92     CMD_BIND_PIPELINE_COMPUTE,
93     CMD_PUSH_CONSTANT,
94     CMD_DRAW,
95     CMD_DISPATCH,
96     CMD_UNSUPPORTED
97 };
98 
99 enum PushConstantUseStageType
100 {
101     PC_USE_STAGE_NONE   = 0x00000000,
102     PC_USE_STAGE_VERTEX = VK_SHADER_STAGE_VERTEX_BIT,
103     PC_USE_STAGE_TESC   = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
104     PC_USE_STAGE_TESE   = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
105     PC_USE_STAGE_GEOM   = VK_SHADER_STAGE_GEOMETRY_BIT,
106     PC_USE_STAGE_FRAG   = VK_SHADER_STAGE_FRAGMENT_BIT,
107     PC_USE_STAGE_ALL    = VK_SHADER_STAGE_ALL
108 };
109 
110 typedef uint32_t PushConstantUseStage;
111 
112 struct CommandData
113 {
114     CommandType cType;
115     int32_t rangeNdx;
116 };
117 
118 struct PushConstantData
119 {
120     struct PushConstantRange
121     {
122         VkShaderStageFlags shaderStage;
123         uint32_t offset;
124         uint32_t size;
125     } range;
126     struct PushConstantUpdate
127     {
128         uint32_t offset;
129         uint32_t size;
130     } update;
131 };
132 
133 // These values will be loaded from push constants and used as an index
134 static const uint32_t DYNAMIC_VEC_INDEX = 2u;
135 static const uint32_t DYNAMIC_MAT_INDEX = 0u;
136 static const uint32_t DYNAMIC_ARR_INDEX = 3u;
137 
138 // These reference values will be compared in the shader to ensure the correct index was read
139 static const float DYNAMIC_VEC_CONSTANT = 0.25f;
140 static const float DYNAMIC_MAT_CONSTANT = 0.50f;
141 static const float DYNAMIC_ARR_CONSTANT = 0.75f;
142 
143 enum IndexType
144 {
145     INDEX_TYPE_CONST_LITERAL = 0,
146     INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR,
147 
148     INDEX_TYPE_LAST
149 };
150 
151 enum ComputeTestType
152 {
153     CTT_SIMPLE = 0,
154     CTT_UNINITIALIZED,
155 
156     CTT_LAST
157 };
158 
getShaderStageNameStr(VkShaderStageFlags stageFlags)159 std::string getShaderStageNameStr(VkShaderStageFlags stageFlags)
160 {
161     const VkShaderStageFlags shaderStages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
162                                                VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
163                                                VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT};
164 
165     const char *shaderStageNames[] = {
166         "VK_SHADER_STAGE_VERTEX_BIT",
167         "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT",
168         "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT",
169         "VK_SHADER_STAGE_GEOMETRY_BIT",
170         "VK_SHADER_STAGE_FRAGMENT_BIT",
171     };
172 
173     std::stringstream shaderStageStr;
174 
175     for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
176     {
177         if (stageFlags & shaderStages[stageNdx])
178         {
179             if (!(shaderStageStr.str().empty()))
180                 shaderStageStr << " | ";
181 
182             shaderStageStr << shaderStageNames[stageNdx];
183         }
184     }
185 
186     return shaderStageStr.str();
187 }
188 
createQuad(const float size,const tcu::Vec4 & color)189 std::vector<Vertex4RGBA> createQuad(const float size, const tcu::Vec4 &color)
190 {
191     std::vector<Vertex4RGBA> vertices;
192 
193     const Vertex4RGBA lowerLeftVertex  = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
194     const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
195     const Vertex4RGBA UpperLeftVertex  = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
196     const Vertex4RGBA UpperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
197 
198     vertices.push_back(lowerLeftVertex);
199     vertices.push_back(lowerRightVertex);
200     vertices.push_back(UpperLeftVertex);
201     vertices.push_back(UpperLeftVertex);
202     vertices.push_back(lowerRightVertex);
203     vertices.push_back(UpperRightVertex);
204 
205     return vertices;
206 }
207 
pushConstants(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkPipelineLayout layout,VkShaderStageFlags stageFlags,uint32_t offset,uint32_t size,const void * pValues,bool pushConstant2)208 void pushConstants(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkPipelineLayout layout,
209                    VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void *pValues,
210                    bool pushConstant2)
211 {
212     if (pushConstant2)
213     {
214 #ifndef CTS_USES_VULKANSC
215         vk::VkPushConstantsInfoKHR pushConstantInfo = {
216             VK_STRUCTURE_TYPE_PUSH_CONSTANTS_INFO_KHR, // VkStructureType sType;
217             DE_NULL,                                   // const void* pNext;
218             layout,                                    // VkPipelineLayout layout;
219             stageFlags,                                // VkShaderStageFlags stageFlags;
220             offset,                                    // uint32_t offset;
221             size,                                      // uint32_t size;
222             pValues,                                   // const void* pValues;
223         };
224         vk.cmdPushConstants2KHR(cmdBuffer, &pushConstantInfo);
225 #endif
226     }
227     else
228     {
229         vk.cmdPushConstants(cmdBuffer, layout, stageFlags, offset, size, pValues);
230     }
231 }
232 
233 class PushConstantGraphicsTestInstance : public vkt::TestInstance
234 {
235 public:
236     PushConstantGraphicsTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
237                                      const uint32_t rangeCount,
238                                      const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
239                                      const bool multipleUpdate, const IndexType indexType, const bool pushConstant2,
240                                      const PushConstantUseStage pcUsedStage = PC_USE_STAGE_ALL);
241     virtual ~PushConstantGraphicsTestInstance(void);
242     void init(void);
243     virtual tcu::TestStatus iterate(void);
244     virtual std::vector<VkPushConstantRange> getPushConstantRanges(void)                         = 0;
245     virtual void updatePushConstants(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout) = 0;
246     virtual void setReferenceColor(tcu::Vec4 initColor)                                          = 0;
247     void createShaderModule(const DeviceInterface &vk, VkDevice device, const BinaryCollection &programCollection,
248                             const char *name, ShaderWrapper *module);
249     tcu::TestStatus verifyImage(void);
250 
251 protected:
252     const PipelineConstructionType m_pipelineConstructionType;
253     std::vector<Vertex4RGBA> m_vertices;
254     const uint32_t m_rangeCount;
255     PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
256     const IndexType m_indexType;
257     const PushConstantUseStage m_pcUsedStage;
258     bool m_pushConstant2;
259 
260 private:
261     const tcu::UVec2 m_renderSize;
262     const VkFormat m_colorFormat;
263     const bool m_multipleUpdate;
264 
265     VkImageCreateInfo m_colorImageCreateInfo;
266     Move<VkImage> m_colorImage;
267     de::MovePtr<Allocation> m_colorImageAlloc;
268     Move<VkImageView> m_colorAttachmentView;
269     RenderPassWrapper m_renderPass;
270     Move<VkFramebuffer> m_framebuffer;
271 
272     ShaderWrapper m_vertexShaderModule;
273     ShaderWrapper m_fragmentShaderModule;
274     ShaderWrapper m_geometryShaderModule;
275     ShaderWrapper m_tessControlShaderModule;
276     ShaderWrapper m_tessEvaluationShaderModule;
277 
278     VkShaderStageFlags m_shaderFlags;
279     std::vector<VkPipelineShaderStageCreateInfo> m_shaderStage;
280 
281     Move<VkBuffer> m_vertexBuffer;
282     de::MovePtr<Allocation> m_vertexBufferAlloc;
283 
284     Move<VkBuffer> m_uniformBuffer;
285     de::MovePtr<Allocation> m_uniformBufferAlloc;
286     Move<VkDescriptorPool> m_descriptorPool;
287     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
288     Move<VkDescriptorSet> m_descriptorSet;
289 
290     PipelineLayoutWrapper m_preRasterizationStatePipelineLayout;
291     PipelineLayoutWrapper m_fragmentStatePipelineLayout;
292     GraphicsPipelineWrapper m_graphicsPipeline;
293 
294     Move<VkCommandPool> m_cmdPool;
295     Move<VkCommandBuffer> m_cmdBuffer;
296 };
297 
createShaderModule(const DeviceInterface & vk,VkDevice device,const BinaryCollection & programCollection,const char * name,ShaderWrapper * module)298 void PushConstantGraphicsTestInstance::createShaderModule(const DeviceInterface &vk, VkDevice device,
299                                                           const BinaryCollection &programCollection, const char *name,
300                                                           ShaderWrapper *module)
301 {
302     *module = ShaderWrapper(vk, device, programCollection.get(name), 0);
303 }
304 
PushConstantGraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],bool multipleUpdate,IndexType indexType,const bool pushConstant2,const PushConstantUseStage pcUsedStage)305 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance(
306     Context &context, const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
307     const PushConstantData pushConstantRange[MAX_RANGE_COUNT], bool multipleUpdate, IndexType indexType,
308     const bool pushConstant2, const PushConstantUseStage pcUsedStage)
309     : vkt::TestInstance(context)
310     , m_pipelineConstructionType(pipelineConstructionType)
311     , m_rangeCount(rangeCount)
312     , m_indexType(indexType)
313     , m_pcUsedStage(pcUsedStage)
314     , m_pushConstant2(pushConstant2)
315     , m_renderSize(32, 32)
316     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
317     , m_multipleUpdate(multipleUpdate)
318     , m_shaderFlags(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
319     , m_graphicsPipeline(m_context.getInstanceInterface(), m_context.getDeviceInterface(),
320                          m_context.getPhysicalDevice(), m_context.getDevice(), m_context.getDeviceExtensions(),
321                          pipelineConstructionType)
322 {
323     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
324 }
325 
init(void)326 void PushConstantGraphicsTestInstance::init(void)
327 {
328     const DeviceInterface &vk       = m_context.getDeviceInterface();
329     const VkDevice vkDevice         = m_context.getDevice();
330     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
331     SimpleAllocator memAlloc(
332         vk, vkDevice,
333         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
334     const VkComponentMapping componentMappingRGBA             = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
335                                                                  VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
336     const std::vector<VkPushConstantRange> pushConstantRanges = getPushConstantRanges();
337     bool useTessellation                                      = false;
338     bool useGeometry                                          = false;
339 
340     // Create color image
341     {
342         const VkImageCreateInfo colorImageParams = {
343             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
344             DE_NULL,                                                               // const void* pNext;
345             0u,                                                                    // VkImageCreateFlags flags;
346             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
347             m_colorFormat,                                                         // VkFormat format;
348             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
349             1u,                                                                    // uint32_t mipLevels;
350             1u,                                                                    // uint32_t arrayLayers;
351             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
352             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
353             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
354             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
355             1u,                                                                    // uint32_t queueFamilyIndexCount;
356             &queueFamilyIndex,         // const uint32_t* pQueueFamilyIndices;
357             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
358         };
359 
360         m_colorImageCreateInfo = colorImageParams;
361         m_colorImage           = createImage(vk, vkDevice, &m_colorImageCreateInfo);
362 
363         // Allocate and bind color image memory
364         m_colorImageAlloc =
365             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
366         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
367                                     m_colorImageAlloc->getOffset()));
368     }
369 
370     // Create color attachment view
371     {
372         const VkImageViewCreateInfo colorAttachmentViewParams = {
373             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // VkStructureType sType;
374             DE_NULL,                                     // const void* pNext;
375             0u,                                          // VkImageViewCreateFlags flags;
376             *m_colorImage,                               // VkImage image;
377             VK_IMAGE_VIEW_TYPE_2D,                       // VkImageViewType viewType;
378             m_colorFormat,                               // VkFormat format;
379             componentMappingRGBA,                        // VkChannelMapping channels;
380             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
381         };
382 
383         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
384     }
385 
386     // Create render pass
387     m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, m_colorFormat);
388 
389     // Create framebuffer
390     {
391         const VkImageView attachmentBindInfos[1] = {*m_colorAttachmentView};
392 
393         const VkFramebufferCreateInfo framebufferParams = {
394             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
395             DE_NULL,                                   // const void* pNext;
396             0u,                                        // VkFramebufferCreateFlags flags;
397             *m_renderPass,                             // VkRenderPass renderPass;
398             1u,                                        // uint32_t attachmentCount;
399             attachmentBindInfos,                       // const VkImageView* pAttachments;
400             (uint32_t)m_renderSize.x(),                // uint32_t width;
401             (uint32_t)m_renderSize.y(),                // uint32_t height;
402             1u                                         // uint32_t layers;
403         };
404 
405         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
406     }
407 
408     // Create pipeline layout
409     {
410         // create descriptor set layout
411         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
412                                     .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
413                                     .build(vk, vkDevice);
414 
415         // create descriptor pool
416         m_descriptorPool = DescriptorPoolBuilder()
417                                .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
418                                .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
419 
420         // create uniform buffer
421         const VkBufferCreateInfo uniformBufferCreateInfo = {
422             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
423             DE_NULL,                              // const void* pNext;
424             0u,                                   // VkBufferCreateFlags    flags
425             16u,                                  // VkDeviceSize size;
426             VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,   // VkBufferUsageFlags usage;
427             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
428             1u,                                   // uint32_t queueFamilyCount;
429             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
430         };
431 
432         m_uniformBuffer      = createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
433         m_uniformBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer),
434                                                  MemoryRequirement::HostVisible);
435         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(),
436                                      m_uniformBufferAlloc->getOffset()));
437 
438         const tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
439         deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
440         flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
441 
442         // create and update descriptor set
443         const VkDescriptorSetAllocateInfo allocInfo = {
444             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                             sType;
445             DE_NULL,                                        // const void*                                 pNext;
446             *m_descriptorPool,         // VkDescriptorPool                            descriptorPool;
447             1u,                        // uint32_t                                    setLayoutCount;
448             &(*m_descriptorSetLayout), // const VkDescriptorSetLayout*                pSetLayouts;
449         };
450         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
451 
452         const VkDescriptorBufferInfo descriptorInfo =
453             makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
454 
455         DescriptorSetUpdateBuilder()
456             .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
457                          VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
458             .update(vk, vkDevice);
459 
460         // create pipeline layout
461 #ifndef CTS_USES_VULKANSC
462         VkPipelineLayoutCreateFlags pipelineLayoutFlags =
463             (vk::isConstructionTypeLibrary(m_pipelineConstructionType)) ?
464                 uint32_t(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT) :
465                 0u;
466 #else
467         VkPipelineLayoutCreateFlags pipelineLayoutFlags = 0u;
468 #endif // CTS_USES_VULKANSC
469         VkPipelineLayoutCreateInfo pipelineLayoutParams{
470             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
471             DE_NULL,                                       // const void* pNext;
472             pipelineLayoutFlags,                           // VkPipelineLayoutCreateFlags flags;
473             1u,                                            // uint32_t setLayoutCount;
474             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
475             (uint32_t)pushConstantRanges.size(),           // uint32_t pushConstantRangeCount;
476             &pushConstantRanges.front()                    // const VkPushConstantRange* pPushConstantRanges;
477         };
478 
479         m_preRasterizationStatePipelineLayout =
480             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
481         pipelineLayoutParams.setLayoutCount = 0u;
482         pipelineLayoutParams.pSetLayouts    = DE_NULL;
483         m_fragmentStatePipelineLayout =
484             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
485     }
486 
487     // Create shaders
488     {
489         for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
490         {
491             if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
492             {
493                 m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
494             }
495             if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
496             {
497                 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
498             }
499             if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
500             {
501                 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
502             }
503         }
504 
505         VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
506 
507         createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", &m_vertexShaderModule);
508         if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
509             m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
510         {
511             if (features.tessellationShader == VK_FALSE)
512             {
513                 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
514             }
515             createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", &m_tessControlShaderModule);
516             createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tese",
517                                &m_tessEvaluationShaderModule);
518             useTessellation = true;
519         }
520         if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
521         {
522             if (features.geometryShader == VK_FALSE)
523             {
524                 TCU_THROW(NotSupportedError, "Geometry Not Supported");
525             }
526             createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", &m_geometryShaderModule);
527             useGeometry = true;
528         }
529         createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", &m_fragmentShaderModule);
530     }
531 
532     // Create pipeline
533     {
534         const VkVertexInputBindingDescription vertexInputBindingDescription = {
535             0u,                         // uint32_t binding;
536             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
537             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
538         };
539 
540         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
541             {
542                 0u,                            // uint32_t location;
543                 0u,                            // uint32_t binding;
544                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
545                 0u                             // uint32_t offsetInBytes;
546             },
547             {
548                 1u,                            // uint32_t location;
549                 0u,                            // uint32_t binding;
550                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
551                 offsetof(Vertex4RGBA, color),  // uint32_t offset;
552             }};
553 
554         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
555             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
556             DE_NULL,                                                   // const void* pNext;
557             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
558             1u,                                                        // uint32_t bindingCount;
559             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
560             2u,                              // uint32_t attributeCount;
561             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
562         };
563 
564         const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ?
565                                                  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
566                                                  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
567 
568         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
569         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
570 
571         m_graphicsPipeline.setMonolithicPipelineLayout(m_preRasterizationStatePipelineLayout)
572             .setDefaultRasterizationState()
573             .setDefaultDepthStencilState()
574             .setDefaultMultisampleState()
575             .setDefaultColorBlendState()
576             .setDefaultTopology(topology)
577             .setupVertexInputState(&vertexInputStateParams)
578             .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
579                                               0u, m_vertexShaderModule, DE_NULL,
580                                               useTessellation ? m_tessControlShaderModule : ShaderWrapper(),
581                                               useTessellation ? m_tessEvaluationShaderModule : ShaderWrapper(),
582                                               useGeometry ? m_geometryShaderModule : ShaderWrapper())
583             .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
584             .setupFragmentOutputState(*m_renderPass)
585             .buildPipeline();
586     }
587 
588     // Create vertex buffer
589     {
590         m_vertices = createQuad(1.0f, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
591 
592         const VkBufferCreateInfo vertexBufferParams = {
593             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
594             DE_NULL,                                                 // const void* pNext;
595             0u,                                                      // VkBufferCreateFlags flags;
596             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
597             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
598             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
599             1u,                                                      // uint32_t queueFamilyCount;
600             &queueFamilyIndex                                        // const uint32_t* pQueueFamilyIndices;
601         };
602 
603         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
604         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
605                                                 MemoryRequirement::HostVisible);
606 
607         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
608                                      m_vertexBufferAlloc->getOffset()));
609 
610         // Load vertices into vertex buffer
611         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
612         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
613     }
614 
615     // Create command pool
616     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
617 
618     // Create command buffer
619     {
620         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
621 
622         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
623 
624         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
625 
626         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
627                            attachmentClearValue);
628 
629         // Update push constant values
630         updatePushConstants(*m_cmdBuffer, *m_preRasterizationStatePipelineLayout);
631 
632         // draw quad
633         const VkDeviceSize triangleOffset = (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
634 
635         for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
636         {
637             VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
638 
639             if (m_multipleUpdate)
640             {
641                 pushConstants(vk, *m_cmdBuffer, *m_preRasterizationStatePipelineLayout,
642                               m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset,
643                               m_pushConstantRange[0].range.size, &triangleNdx, m_pushConstant2);
644             }
645 
646             m_graphicsPipeline.bind(*m_cmdBuffer);
647             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
648             vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
649                                      *m_preRasterizationStatePipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
650 
651             vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
652         }
653 
654         m_renderPass.end(vk, *m_cmdBuffer);
655         endCommandBuffer(vk, *m_cmdBuffer);
656     }
657 }
658 
~PushConstantGraphicsTestInstance(void)659 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance(void)
660 {
661 }
662 
iterate(void)663 tcu::TestStatus PushConstantGraphicsTestInstance::iterate(void)
664 {
665     init();
666 
667     const DeviceInterface &vk = m_context.getDeviceInterface();
668     const VkDevice vkDevice   = m_context.getDevice();
669     const VkQueue queue       = m_context.getUniversalQueue();
670 
671     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
672 
673     return verifyImage();
674 }
675 
verifyImage(void)676 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage(void)
677 {
678     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
679     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
680     const ColorVertexShader vertexShader;
681     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
682     const rr::Program program(&vertexShader, &fragmentShader);
683     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
684     bool compareOk = false;
685 
686     // Render reference image
687     {
688         if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
689         {
690             m_vertices =
691                 createQuad(((m_pcUsedStage & PC_USE_STAGE_GEOM) ? 0.5f : 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
692         }
693 
694         setReferenceColor(m_vertices[0].color);
695 
696         if (m_multipleUpdate)
697         {
698             for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
699             {
700                 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
701             }
702             for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
703             {
704                 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
705             }
706         }
707 
708         for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
709         {
710             rr::RenderState renderState(refRenderer.getViewportState(),
711                                         m_context.getDeviceProperties().limits.subPixelPrecisionBits);
712 
713             refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES,
714                              std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
715                                                       m_vertices.begin() + (triangleNdx + 1) * 3));
716         }
717     }
718 
719     // Compare result with reference image
720     {
721         const DeviceInterface &vk       = m_context.getDeviceInterface();
722         const VkDevice vkDevice         = m_context.getDevice();
723         const VkQueue queue             = m_context.getUniversalQueue();
724         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
725         SimpleAllocator allocator(
726             vk, vkDevice,
727             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
728         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
729                                                                     *m_colorImage, m_colorFormat, m_renderSize);
730 
731         compareOk = tcu::intThresholdPositionDeviationCompare(
732             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
733             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
734     }
735 
736     if (compareOk)
737         return tcu::TestStatus::pass("Result image matches reference");
738     else
739         return tcu::TestStatus::fail("Image mismatch");
740 }
741 
742 class PushConstantGraphicsDisjointInstance : public PushConstantGraphicsTestInstance
743 {
744 public:
745     PushConstantGraphicsDisjointInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
746                                          const uint32_t rangeCount,
747                                          const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
748                                          const bool multipleUpdate, const IndexType indexType, const bool pushConstant2,
749                                          const PushConstantUseStage pcUsedStage = PC_USE_STAGE_ALL);
750     virtual ~PushConstantGraphicsDisjointInstance(void);
751     std::vector<VkPushConstantRange> getPushConstantRanges(void);
752     void updatePushConstants(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
753     void setReferenceColor(tcu::Vec4 initColor);
754 };
755 
PushConstantGraphicsDisjointInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const bool multipleUpdate,const IndexType indexType,const bool pushConstant2,const PushConstantUseStage pcUsedStage)756 PushConstantGraphicsDisjointInstance::PushConstantGraphicsDisjointInstance(
757     Context &context, const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
758     const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool multipleUpdate, const IndexType indexType,
759     const bool pushConstant2, const PushConstantUseStage pcUsedStage)
760     : PushConstantGraphicsTestInstance(context, pipelineConstructionType, rangeCount, pushConstantRange, multipleUpdate,
761                                        indexType, pushConstant2, pcUsedStage)
762 {
763     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
764 }
765 
~PushConstantGraphicsDisjointInstance(void)766 PushConstantGraphicsDisjointInstance::~PushConstantGraphicsDisjointInstance(void)
767 {
768 }
769 
getPushConstantRanges(void)770 std::vector<VkPushConstantRange> PushConstantGraphicsDisjointInstance::getPushConstantRanges(void)
771 {
772     std::vector<VkPushConstantRange> pushConstantRanges;
773 
774     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
775     {
776         const VkPushConstantRange pushConstantRange = {m_pushConstantRange[rangeNdx].range.shaderStage,
777                                                        m_pushConstantRange[rangeNdx].range.offset,
778                                                        m_pushConstantRange[rangeNdx].range.size};
779 
780         pushConstantRanges.push_back(pushConstantRange);
781     }
782 
783     return pushConstantRanges;
784 }
785 
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)786 void PushConstantGraphicsDisjointInstance::updatePushConstants(VkCommandBuffer cmdBuffer,
787                                                                VkPipelineLayout pipelineLayout)
788 {
789     const DeviceInterface &vk = m_context.getDeviceInterface();
790     std::vector<tcu::Vec4> color(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
791     std::vector<tcu::Vec4> allOnes(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
792 
793     switch (m_indexType)
794     {
795     case INDEX_TYPE_CONST_LITERAL:
796         // Do nothing
797         break;
798     case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
799         // Stick our dynamic index at the beginning of a vector
800         color[0] = tcu::Vec4(float(DYNAMIC_VEC_INDEX), float(DYNAMIC_MAT_INDEX), float(DYNAMIC_ARR_INDEX), 1.0f);
801 
802         // Place our reference values at each type offset
803 
804         // vec4[i]
805         DE_ASSERT(DYNAMIC_VEC_INDEX <= 3);
806         color[1]                    = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
807         color[1][DYNAMIC_VEC_INDEX] = DYNAMIC_VEC_CONSTANT;
808 
809         // mat2[i][0]
810         DE_ASSERT(DYNAMIC_MAT_INDEX <= 1);
811         color[2]                        = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
812         color[2][DYNAMIC_MAT_INDEX * 2] = DYNAMIC_MAT_CONSTANT;
813 
814         // float[i]
815         DE_ASSERT(DYNAMIC_ARR_INDEX <= 3);
816         color[3]                    = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
817         color[3][DYNAMIC_ARR_INDEX] = DYNAMIC_ARR_CONSTANT;
818         break;
819     default:
820         DE_FATAL("Unhandled IndexType");
821         break;
822     }
823 
824     const uint32_t kind = 2u;
825     const void *value   = DE_NULL;
826 
827     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
828     {
829         value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void *)(&kind) : (void *)(&color[0]);
830 
831         pushConstants(vk, cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage,
832                       m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value,
833                       m_pushConstant2);
834 
835         if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
836         {
837             value = (void *)(&allOnes[0]);
838             pushConstants(vk, cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage,
839                           m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value,
840                           m_pushConstant2);
841         }
842     }
843 }
844 
setReferenceColor(tcu::Vec4 initColor)845 void PushConstantGraphicsDisjointInstance::setReferenceColor(tcu::Vec4 initColor)
846 {
847     DE_UNREF(initColor);
848 
849     const tcu::Vec4 color = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
850 
851     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
852     {
853         if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
854         {
855             for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
856             {
857                 m_vertices[vertexNdx].color.xyzw() = color;
858             }
859         }
860     }
861 }
862 
863 class PushConstantGraphicsOverlapTestInstance : public PushConstantGraphicsTestInstance
864 {
865 public:
866     PushConstantGraphicsOverlapTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
867                                             const uint32_t rangeCount,
868                                             const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
869                                             const bool multipleUpdate, const IndexType indexType,
870                                             const bool pushConstant2,
871                                             const PushConstantUseStage pcUsedStage = PC_USE_STAGE_ALL);
872     virtual ~PushConstantGraphicsOverlapTestInstance(void);
873     std::vector<VkPushConstantRange> getPushConstantRanges(void);
874     std::vector<VkPushConstantRange> getPushConstantUpdates(void);
875     void updatePushConstants(VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
876     void setReferenceColor(tcu::Vec4 initColor);
877 
878 private:
879     const std::vector<float> m_colorData;
880     std::vector<float> m_referenceData;
881 };
882 
generateColorData(uint32_t numBytes)883 std::vector<float> generateColorData(uint32_t numBytes)
884 {
885     DE_ASSERT(numBytes % 4u == 0u);
886 
887     std::vector<float> colorData;
888 
889     deRandom random;
890     deRandom_init(&random, numBytes);
891 
892     for (uint32_t elementNdx = 0u; elementNdx < numBytes / 4u; elementNdx++)
893         colorData.push_back(deRandom_getFloat(&random));
894 
895     return colorData;
896 }
897 
PushConstantGraphicsOverlapTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const bool multipleUpdate,const IndexType indexType,const bool pushConstant2,const PushConstantUseStage pcUsedStage)898 PushConstantGraphicsOverlapTestInstance::PushConstantGraphicsOverlapTestInstance(
899     Context &context, const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
900     const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool multipleUpdate, const IndexType indexType,
901     const bool pushConstant2, const PushConstantUseStage pcUsedStage)
902     : PushConstantGraphicsTestInstance(context, pipelineConstructionType, rangeCount, pushConstantRange, multipleUpdate,
903                                        indexType, pushConstant2, pcUsedStage)
904     , m_colorData(generateColorData(256u))
905 {
906     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
907 }
908 
~PushConstantGraphicsOverlapTestInstance(void)909 PushConstantGraphicsOverlapTestInstance::~PushConstantGraphicsOverlapTestInstance(void)
910 {
911 }
912 
getPushConstantRanges(void)913 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantRanges(void)
914 {
915     // Find push constant ranges for each shader stage
916     const VkShaderStageFlags shaderStages[] = {
917         VK_SHADER_STAGE_VERTEX_BIT,
918         VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
919         VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
920         VK_SHADER_STAGE_GEOMETRY_BIT,
921         VK_SHADER_STAGE_FRAGMENT_BIT,
922     };
923 
924     std::vector<VkPushConstantRange> pushConstantRanges;
925 
926     m_context.getTestContext().getLog() << tcu::TestLog::Section("Ranges", "Push constant ranges");
927 
928     for (uint32_t stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
929     {
930         uint32_t firstByte = ~0u;
931         uint32_t lastByte  = 0u;
932 
933         for (uint32_t rangeNdx = 0u; rangeNdx < m_rangeCount; rangeNdx++)
934         {
935             if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStages[stageNdx])
936             {
937                 firstByte = deMinu32(firstByte, m_pushConstantRange[rangeNdx].range.offset);
938                 lastByte  = deMaxu32(lastByte, m_pushConstantRange[rangeNdx].range.offset +
939                                                    m_pushConstantRange[rangeNdx].range.size);
940             }
941         }
942 
943         if (firstByte != ~0u)
944         {
945             const VkPushConstantRange pushConstantRange = {
946                 shaderStages[stageNdx], // VkShaderStageFlags    stageFlags
947                 firstByte,              // uint32_t              offset
948                 lastByte - firstByte    // uint32_t              size
949             };
950 
951             pushConstantRanges.push_back(pushConstantRange);
952 
953             m_context.getTestContext().getLog()
954                 << tcu::TestLog::Message << "VkShaderStageFlags    stageFlags    "
955                 << getShaderStageNameStr(shaderStages[stageNdx]) << ",\n"
956                 << "uint32_t              offset        " << pushConstantRange.offset << ",\n"
957                 << "uint32_t              size          " << pushConstantRange.size << "\n"
958                 << tcu::TestLog::EndMessage;
959         }
960     }
961 
962     m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
963 
964     return pushConstantRanges;
965 }
966 
getPushConstantUpdates(void)967 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantUpdates(void)
968 {
969     VkShaderStageFlags lastStageFlags = (VkShaderStageFlags)~0u;
970     std::vector<VkPushConstantRange> pushConstantUpdates;
971 
972     // Find matching shader stages for every 4 byte chunk
973     for (uint32_t offset = 0u; offset < 128u; offset += 4u)
974     {
975         VkShaderStageFlags stageFlags = (VkShaderStageFlags)0u;
976         bool updateRange              = false;
977 
978         // For each byte in the range specified by offset and size and for each push constant range that overlaps that byte,
979         // stageFlags must include all stages in that push constant range's VkPushConstantRange::stageFlags
980         for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
981         {
982             const uint32_t rangeStart = m_pushConstantRange[rangeNdx].range.offset;
983             const uint32_t rangeEnd   = rangeStart + m_pushConstantRange[rangeNdx].range.size;
984 
985             const uint32_t updateStart = m_pushConstantRange[rangeNdx].update.offset;
986             const uint32_t updateEnd   = updateStart + m_pushConstantRange[rangeNdx].update.size;
987 
988             updateRange |= (updateStart <= offset && updateEnd >= offset + 4u);
989 
990             DE_ASSERT(rangeEnd <= 128u);
991 
992             if (rangeStart <= offset && rangeEnd >= offset + 4u)
993                 stageFlags |= m_pushConstantRange[rangeNdx].range.shaderStage;
994         }
995 
996         // Skip chunks with no updates
997         if (!stageFlags || !updateRange)
998             continue;
999 
1000         // Add new update entry
1001         if (stageFlags != lastStageFlags)
1002         {
1003             const VkPushConstantRange update = {
1004                 stageFlags, // VkShaderStageFlags    stageFlags;
1005                 offset,     // uint32_t              offset;
1006                 4u          // uint32_t              size;
1007             };
1008 
1009             pushConstantUpdates.push_back(update);
1010             lastStageFlags = stageFlags;
1011         }
1012         // Increase current update entry size
1013         else
1014         {
1015             DE_ASSERT(pushConstantUpdates.size() > 0u);
1016             pushConstantUpdates.back().size += 4u;
1017         }
1018     }
1019 
1020     return pushConstantUpdates;
1021 }
1022 
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)1023 void PushConstantGraphicsOverlapTestInstance::updatePushConstants(VkCommandBuffer cmdBuffer,
1024                                                                   VkPipelineLayout pipelineLayout)
1025 {
1026     const DeviceInterface &vk                                  = m_context.getDeviceInterface();
1027     const std::vector<VkPushConstantRange> pushConstantUpdates = getPushConstantUpdates();
1028 
1029     m_referenceData.resize(m_colorData.size(), 0.0f);
1030 
1031     m_context.getTestContext().getLog() << tcu::TestLog::Section("Updates", "Push constant updates");
1032 
1033     for (uint32_t pushNdx = 0u; pushNdx < pushConstantUpdates.size(); pushNdx++)
1034     {
1035         m_context.getTestContext().getLog()
1036             << tcu::TestLog::Message << "VkShaderStageFlags    stageFlags    "
1037             << getShaderStageNameStr(pushConstantUpdates[pushNdx].stageFlags) << ",\n"
1038             << "uint32_t              offset        " << pushConstantUpdates[pushNdx].offset << ",\n"
1039             << "uint32_t              size          " << pushConstantUpdates[pushNdx].size << ",\n"
1040             << "const void*           pValues       " << &m_colorData[pushConstantUpdates[pushNdx].offset / 2u] << "\n"
1041             << tcu::TestLog::EndMessage;
1042 
1043         pushConstants(vk, cmdBuffer, pipelineLayout, pushConstantUpdates[pushNdx].stageFlags,
1044                       pushConstantUpdates[pushNdx].offset, pushConstantUpdates[pushNdx].size,
1045                       &m_colorData[pushConstantUpdates[pushNdx].offset / 2u], m_pushConstant2);
1046 
1047         // Copy push constant values to reference buffer
1048         DE_ASSERT((pushConstantUpdates[pushNdx].offset / 2u + pushConstantUpdates[pushNdx].size) <
1049                   4u * m_colorData.size());
1050 
1051         if (m_pcUsedStage & pushConstantUpdates[pushNdx].stageFlags)
1052             deMemcpy(&m_referenceData.at(pushConstantUpdates[pushNdx].offset / 4u),
1053                      &m_colorData.at(pushConstantUpdates[pushNdx].offset / 2u), pushConstantUpdates[pushNdx].size);
1054     }
1055 
1056     m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
1057 }
1058 
setReferenceColor(tcu::Vec4 initColor)1059 void PushConstantGraphicsOverlapTestInstance::setReferenceColor(tcu::Vec4 initColor)
1060 {
1061     tcu::Vec4 expectedColor = initColor;
1062 
1063     // Calculate reference color
1064     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1065     {
1066         const uint32_t offset = m_pushConstantRange[rangeNdx].range.offset / 4u;
1067         const uint32_t size   = m_pushConstantRange[rangeNdx].range.size / 4u;
1068 
1069         if (m_pcUsedStage & m_pushConstantRange[rangeNdx].range.shaderStage)
1070         {
1071             const uint32_t numComponents = (size < 4u) ? size : 4u;
1072             const uint32_t colorNdx      = (offset + size - numComponents);
1073 
1074             for (uint32_t componentNdx = 0u; componentNdx < numComponents; componentNdx++)
1075                 expectedColor[componentNdx] += m_referenceData[colorNdx + componentNdx];
1076         }
1077     }
1078 
1079     expectedColor = tcu::min(tcu::mod(expectedColor, tcu::Vec4(2.0f)), 2.0f - tcu::mod(expectedColor, tcu::Vec4(2.0f)));
1080 
1081     for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
1082     {
1083         m_vertices[vertexNdx].color.xyzw() = expectedColor;
1084     }
1085 }
1086 
1087 class PushConstantGraphicsTest : public vkt::TestCase
1088 {
1089 public:
1090     PushConstantGraphicsTest(tcu::TestContext &testContext, const std::string &name,
1091                              const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
1092                              const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool multipleUpdate,
1093                              const IndexType indexType, const bool pushConstant2,
1094                              const PushConstantUseStage pcUsedStage = PC_USE_STAGE_ALL);
1095     virtual ~PushConstantGraphicsTest(void);
1096 
1097     virtual void checkSupport(Context &context) const;
1098     virtual void initPrograms(SourceCollections &sourceCollections) const = 0;
1099     virtual TestInstance *createInstance(Context &context) const          = 0;
1100     RangeSizeCase getRangeSizeCase(uint32_t rangeSize) const;
1101 
1102 protected:
1103     const PipelineConstructionType m_pipelineConstructionType;
1104     const uint32_t m_rangeCount;
1105     PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
1106     const bool m_multipleUpdate;
1107     const IndexType m_indexType;
1108     const bool m_pushConstant2;
1109     const PushConstantUseStage m_pcUsedStage;
1110 };
1111 
PushConstantGraphicsTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const bool multipleUpdate,const IndexType indexType,const bool pushConstant2,const PushConstantUseStage pcUsedStage)1112 PushConstantGraphicsTest::PushConstantGraphicsTest(tcu::TestContext &testContext, const std::string &name,
1113                                                    const PipelineConstructionType pipelineConstructionType,
1114                                                    const uint32_t rangeCount,
1115                                                    const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
1116                                                    const bool multipleUpdate, const IndexType indexType,
1117                                                    const bool pushConstant2, const PushConstantUseStage pcUsedStage)
1118     : vkt::TestCase(testContext, name)
1119     , m_pipelineConstructionType(pipelineConstructionType)
1120     , m_rangeCount(rangeCount)
1121     , m_multipleUpdate(multipleUpdate)
1122     , m_indexType(indexType)
1123     , m_pushConstant2(pushConstant2)
1124     , m_pcUsedStage(pcUsedStage)
1125 {
1126     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
1127 }
1128 
~PushConstantGraphicsTest(void)1129 PushConstantGraphicsTest::~PushConstantGraphicsTest(void)
1130 {
1131 }
1132 
checkSupport(Context & context) const1133 void PushConstantGraphicsTest::checkSupport(Context &context) const
1134 {
1135     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1136                                           m_pipelineConstructionType);
1137 
1138     if (m_pushConstant2)
1139         context.requireDeviceFunctionality("VK_KHR_maintenance6");
1140 }
1141 
getRangeSizeCase(uint32_t rangeSize) const1142 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase(uint32_t rangeSize) const
1143 {
1144     switch (rangeSize)
1145     {
1146     case 8:
1147         return SIZE_CASE_8;
1148     case 4:
1149         return SIZE_CASE_4;
1150     case 12:
1151         return SIZE_CASE_12;
1152     case 16:
1153         return SIZE_CASE_16;
1154     case 32:
1155         return SIZE_CASE_32;
1156     case 36:
1157         return SIZE_CASE_36;
1158     case 48:
1159         return SIZE_CASE_48;
1160     case 128:
1161         return SIZE_CASE_128;
1162     default:
1163         DE_FATAL("Range size unsupported yet");
1164         return SIZE_CASE_UNSUPPORTED;
1165     }
1166 }
1167 
1168 class PushConstantGraphicsDisjointTest : public PushConstantGraphicsTest
1169 {
1170 public:
1171     PushConstantGraphicsDisjointTest(tcu::TestContext &testContext, const std::string &name,
1172                                      const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
1173                                      const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
1174                                      const bool multipleUpdate, const IndexType indexType, const bool pushConstant2,
1175                                      const PushConstantUseStage pcUseStage = PC_USE_STAGE_ALL);
1176     virtual ~PushConstantGraphicsDisjointTest(void);
1177 
1178     virtual void initPrograms(SourceCollections &sourceCollections) const;
1179     virtual TestInstance *createInstance(Context &context) const;
1180 };
1181 
PushConstantGraphicsDisjointTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const bool multipleUpdate,const IndexType indexType,const bool pushConstant2,const PushConstantUseStage pcUseStage)1182 PushConstantGraphicsDisjointTest::PushConstantGraphicsDisjointTest(
1183     tcu::TestContext &testContext, const std::string &name, const PipelineConstructionType pipelineConstructionType,
1184     const uint32_t rangeCount, const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool multipleUpdate,
1185     const IndexType indexType, const bool pushConstant2, const PushConstantUseStage pcUseStage)
1186     : PushConstantGraphicsTest(testContext, name, pipelineConstructionType, rangeCount, pushConstantRange,
1187                                multipleUpdate, indexType, pushConstant2, pcUseStage)
1188 {
1189 }
1190 
~PushConstantGraphicsDisjointTest(void)1191 PushConstantGraphicsDisjointTest::~PushConstantGraphicsDisjointTest(void)
1192 {
1193 }
1194 
initPrograms(SourceCollections & sourceCollections) const1195 void PushConstantGraphicsDisjointTest::initPrograms(SourceCollections &sourceCollections) const
1196 {
1197     std::ostringstream vertexSrc;
1198     std::ostringstream fragmentSrc;
1199     std::ostringstream geometrySrc;
1200     std::ostringstream tessControlSrc;
1201     std::ostringstream tessEvaluationSrc;
1202 
1203     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1204     {
1205         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1206         {
1207             vertexSrc << "#version 450\n"
1208                       << "layout(location = 0) in highp vec4 position;\n"
1209                       << "layout(location = 1) in highp vec4 color;\n"
1210                       << "layout(location = 0) out highp vec4 vtxColor;\n"
1211                       << "out gl_PerVertex { vec4 gl_Position; };\n";
1212 
1213             if (m_pcUsedStage & PC_USE_STAGE_VERTEX)
1214             {
1215                 vertexSrc << "layout(push_constant) uniform Material {\n";
1216 
1217                 switch (m_indexType)
1218                 {
1219                 case INDEX_TYPE_CONST_LITERAL:
1220                     switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1221                     {
1222                     case SIZE_CASE_4:
1223                         vertexSrc << "int kind;\n"
1224                                   << "} matInst;\n";
1225                         break;
1226                     case SIZE_CASE_16:
1227                         vertexSrc << "vec4 color;\n"
1228                                   << "} matInst;\n"
1229                                   << "layout(std140, binding = 0) uniform UniformBuf {\n"
1230                                   << "vec4 element;\n"
1231                                   << "} uniformBuf;\n";
1232                         break;
1233                     case SIZE_CASE_32:
1234                         vertexSrc << "vec4 color[2];\n"
1235                                   << "} matInst;\n";
1236                         break;
1237                     case SIZE_CASE_48:
1238                         vertexSrc << "int unused1;\n"
1239                                   << "vec4 unused2;\n"
1240                                   << "vec4 color;\n"
1241                                   << "} matInst;\n";
1242                         break;
1243                     case SIZE_CASE_128:
1244                         vertexSrc << "vec4 color[8];\n"
1245                                   << "} matInst;\n";
1246                         break;
1247                     default:
1248                         DE_FATAL("Not implemented yet");
1249                         break;
1250                     }
1251                     break;
1252                 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1253                     vertexSrc << "    layout(offset = 0)  vec4 index; \n"
1254                               << "    layout(offset = 16) vec4 vecType; \n"
1255                               << "    layout(offset = 32) mat2 matType; \n"
1256                               << "    layout(offset = 48) float[4] arrType; \n"
1257                               << "} matInst;\n";
1258                     break;
1259                 default:
1260                     DE_FATAL("Unhandled IndexType");
1261                     break;
1262                 }
1263             }
1264 
1265             vertexSrc << "void main()\n"
1266                       << "{\n"
1267                       << "    gl_Position = position;\n";
1268 
1269             if (m_pcUsedStage & PC_USE_STAGE_VERTEX)
1270             {
1271                 switch (m_indexType)
1272                 {
1273                 case INDEX_TYPE_CONST_LITERAL:
1274                     switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1275                     {
1276                     case SIZE_CASE_4:
1277                         vertexSrc << "switch (matInst.kind) {\n"
1278                                   << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
1279                                   << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
1280                                   << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
1281                                   << "default: vtxColor = color; break;}\n"
1282                                   << "}\n";
1283                         break;
1284                     case SIZE_CASE_16:
1285                         vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
1286                                   << "}\n";
1287                         break;
1288                     case SIZE_CASE_32:
1289                         vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
1290                                   << "}\n";
1291                         break;
1292                     case SIZE_CASE_48:
1293                         vertexSrc << "vtxColor = matInst.color;\n"
1294                                   << "}\n";
1295                         break;
1296                     case SIZE_CASE_128:
1297                         vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
1298                                   << "for (int i = 0; i < 8; i++)\n"
1299                                   << "{\n"
1300                                   << "  color = color + matInst.color[i];\n"
1301                                   << "}\n"
1302                                   << "vtxColor = color * 0.125;\n"
1303                                   << "}\n";
1304                         break;
1305                     default:
1306                         DE_FATAL("Not implemented yet");
1307                         break;
1308                     }
1309                     break;
1310                 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1311                 {
1312                     vertexSrc << "    vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1313                               // Mix in gl_Position to (hopefully) prevent optimizing our index away
1314                               << "    int vec_selector = int(abs(gl_Position.x) * 0.0000001 + 0);\n"
1315                               << "    int mat_selector = int(abs(gl_Position.x) * 0.0000001 + 1);\n"
1316                               << "    int arr_selector = int(abs(gl_Position.x) * 0.0000001 + 2);\n";
1317 
1318                     // Use the dynamic index to pull our real index value from push constants
1319                     // Then use that value to index into three variable types
1320                     std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1321                     std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1322                     std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1323 
1324                     // Test vector indexing
1325                     vertexSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1326                               << "        vtxColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1327 
1328                     // Test matrix indexing
1329                     vertexSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1330                               << "        vtxColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1331 
1332                     // Test array indexing
1333                     vertexSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1334                               << "        vtxColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1335 
1336                     vertexSrc << "}\n";
1337                 }
1338                 break;
1339                 default:
1340                     DE_FATAL("Unhandled IndexType");
1341                     break;
1342                 }
1343             }
1344             else
1345             {
1346                 vertexSrc << "    vtxColor = color;\n";
1347                 vertexSrc << "}\n";
1348             }
1349             sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
1350         }
1351 
1352         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1353         {
1354             tessControlSrc << "#version 450\n"
1355                            << "layout (vertices = 3) out;\n";
1356 
1357             if (m_pcUsedStage & PC_USE_STAGE_TESC)
1358             {
1359                 tessControlSrc << "layout(push_constant) uniform TessLevel {\n"
1360                                << "    layout(offset = 24) int level;\n"
1361                                << "} tessLevel;\n";
1362             }
1363 
1364             tessControlSrc << "layout(location = 0) in highp vec4 color[];\n"
1365                            << "layout(location = 0) out highp vec4 vtxColor[];\n"
1366                            << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1367                            << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
1368                            << "void main()\n"
1369                            << "{\n"
1370                            << "  gl_TessLevelInner[0] "
1371                            << ((m_pcUsedStage & PC_USE_STAGE_TESC) ? "= tessLevel.level;\n" : "= 2.0;\n")
1372                            << "  gl_TessLevelOuter[0] "
1373                            << ((m_pcUsedStage & PC_USE_STAGE_TESC) ? "= tessLevel.level;\n" : "= 2.0;\n")
1374                            << "  gl_TessLevelOuter[1] "
1375                            << ((m_pcUsedStage & PC_USE_STAGE_TESC) ? "= tessLevel.level;\n" : "= 2.0;\n")
1376                            << "  gl_TessLevelOuter[2] "
1377                            << ((m_pcUsedStage & PC_USE_STAGE_TESC) ? "= tessLevel.level;\n" : "= 2.0;\n")
1378                            << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1379                            << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1380                            << "}\n";
1381 
1382             sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
1383         }
1384 
1385         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1386         {
1387             tessEvaluationSrc << "#version 450\n"
1388                               << "layout (triangles) in;\n";
1389 
1390             if (m_pcUsedStage & PC_USE_STAGE_TESE)
1391             {
1392                 tessEvaluationSrc << "layout(push_constant) uniform Material {\n"
1393                                   << "    layout(offset = 32) vec4 color;\n"
1394                                   << "} matInst;\n";
1395             }
1396             tessEvaluationSrc << "layout(location = 0) in highp vec4 color[];\n"
1397                               << "layout(location = 0) out highp vec4 vtxColor;\n"
1398                               << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1399                               << "out gl_PerVertex { vec4 gl_Position; };\n"
1400                               << "void main()\n"
1401                               << "{\n"
1402                               << "  gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * "
1403                                  "gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n";
1404 
1405             if (m_pcUsedStage & PC_USE_STAGE_TESE)
1406                 tessEvaluationSrc << "  vtxColor = matInst.color;\n";
1407             else
1408                 tessEvaluationSrc << "  vtxColor = gl_TessCoord.x * color[0] + gl_TessCoord.y * color[1] + "
1409                                      "gl_TessCoord.z * color[2];\n";
1410 
1411             tessEvaluationSrc << "}\n";
1412 
1413             sourceCollections.glslSources.add("color_tese")
1414                 << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
1415         }
1416 
1417         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1418         {
1419             geometrySrc << "#version 450\n"
1420                         << "layout(triangles) in;\n"
1421                         << "layout(triangle_strip, max_vertices=3) out;\n";
1422 
1423             if (m_pcUsedStage & PC_USE_STAGE_GEOM)
1424             {
1425                 geometrySrc << "layout(push_constant) uniform Material {\n"
1426                             << "    layout(offset = 20) int kind;\n"
1427                             << "} matInst;\n";
1428             }
1429 
1430             geometrySrc << "layout(location = 0) in highp vec4 color[];\n"
1431                         << "layout(location = 0) out highp vec4 vtxColor;\n"
1432                         << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
1433                         << "out gl_PerVertex { vec4 gl_Position; };\n"
1434                         << "void main()\n"
1435                         << "{\n"
1436                         << "  for(int i=0; i<3; i++)\n"
1437                         << "  {\n";
1438 
1439             if (m_pcUsedStage & PC_USE_STAGE_GEOM)
1440                 geometrySrc << "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n";
1441             else
1442                 geometrySrc << "    gl_Position.xyz = gl_in[i].gl_Position.xyz;\n";
1443 
1444             geometrySrc << "    gl_Position.w = gl_in[i].gl_Position.w;\n"
1445                         << "    vtxColor = color[i];\n"
1446                         << "    EmitVertex();\n"
1447                         << "  }\n"
1448                         << "  EndPrimitive();\n"
1449                         << "}\n";
1450 
1451             sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
1452         }
1453 
1454         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1455         {
1456             fragmentSrc << "#version 450\n"
1457                         << "layout(location = 0) in highp vec4 vtxColor;\n"
1458                         << "layout(location = 0) out highp vec4 fragColor;\n";
1459 
1460             if (m_pcUsedStage & PC_USE_STAGE_FRAG)
1461             {
1462                 fragmentSrc << "layout(push_constant) uniform Material {\n";
1463 
1464                 switch (m_indexType)
1465                 {
1466                 case INDEX_TYPE_CONST_LITERAL:
1467                     if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1468                     {
1469                         fragmentSrc << "    layout(offset = 0) int kind; \n"
1470                                     << "} matInst;\n";
1471                     }
1472                     else
1473                     {
1474                         fragmentSrc << "    layout(offset = 16) int kind;\n"
1475                                     << "} matInst;\n";
1476                     }
1477 
1478                     fragmentSrc << "void main (void)\n"
1479                                 << "{\n"
1480                                 << "    switch (matInst.kind) {\n"
1481                                 << "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
1482                                 << "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
1483                                 << "    case 2: fragColor = vtxColor; break;\n"
1484                                 << "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
1485                                 << "}\n";
1486                     break;
1487                 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1488                 {
1489                     fragmentSrc << "    layout(offset = 0)  vec4 index; \n"
1490                                 << "    layout(offset = 16) vec4 vecType; \n"
1491                                 << "    layout(offset = 32) mat2 matType; \n"
1492                                 << "    layout(offset = 48) float[4] arrType; \n"
1493                                 << "} matInst;\n";
1494 
1495                     fragmentSrc << "void main (void)\n"
1496                                 << "{\n"
1497                                 << "    fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1498 
1499                                 // Mix in gl_FragCoord to (hopefully) prevent optimizing our index away
1500                                 << "    int vec_selector = int(gl_FragCoord.x * 0.0000001 + 0);\n"
1501                                 << "    int mat_selector = int(gl_FragCoord.x * 0.0000001 + 1);\n"
1502                                 << "    int arr_selector = int(gl_FragCoord.x * 0.0000001 + 2);\n";
1503 
1504                     // Use the dynamic index to pull our real index value from push constants
1505                     // Then use that value to index into three variable types
1506                     std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1507                     std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1508                     std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1509 
1510                     // Test vector indexing
1511                     fragmentSrc << "    if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1512                                 << "        fragColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1513 
1514                     // Test matrix indexing
1515                     fragmentSrc << "    if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1516                                 << "        fragColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1517 
1518                     // Test array indexing
1519                     fragmentSrc << "    if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1520                                 << "        fragColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1521 
1522                     fragmentSrc << "}\n";
1523                 }
1524                 break;
1525                 default:
1526                     DE_FATAL("Unhandled IndexType");
1527                     break;
1528                 }
1529             }
1530             else
1531             {
1532                 fragmentSrc << "void main (void)\n"
1533                             << "{\n"
1534                             << "    fragColor = vtxColor;\n"
1535                             << "}\n";
1536             }
1537 
1538             sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1539         }
1540     }
1541 
1542     // add a pass through fragment shader if it's not activated in push constant ranges
1543     if (fragmentSrc.str().empty())
1544     {
1545         fragmentSrc << "#version 450\n"
1546                     << "layout(location = 0) in highp vec4 vtxColor;\n"
1547                     << "layout(location = 0) out highp vec4 fragColor;\n"
1548                     << "void main (void)\n"
1549                     << "{\n"
1550                     << "    fragColor = vtxColor;\n"
1551                     << "}\n";
1552 
1553         sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1554     }
1555 }
1556 
createInstance(Context & context) const1557 TestInstance *PushConstantGraphicsDisjointTest::createInstance(Context &context) const
1558 {
1559     return new PushConstantGraphicsDisjointInstance(context, m_pipelineConstructionType, m_rangeCount,
1560                                                     m_pushConstantRange, m_multipleUpdate, m_indexType, m_pushConstant2,
1561                                                     m_pcUsedStage);
1562 }
1563 
1564 class PushConstantGraphicsOverlapTest : public PushConstantGraphicsTest
1565 {
1566 public:
1567     PushConstantGraphicsOverlapTest(tcu::TestContext &testContext, const std::string &name,
1568                                     const PipelineConstructionType pipelineConstructionType, const uint32_t rangeCount,
1569                                     const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool pushConstant2,
1570                                     const PushConstantUseStage pcUsedStage = PC_USE_STAGE_ALL);
1571     virtual ~PushConstantGraphicsOverlapTest(void);
1572     std::string getPushConstantDeclarationStr(VkShaderStageFlags shaderStage) const;
1573     virtual void initPrograms(SourceCollections &sourceCollections) const;
1574     virtual TestInstance *createInstance(Context &context) const;
1575 };
1576 
PushConstantGraphicsOverlapTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const uint32_t rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const bool pushConstant2,const PushConstantUseStage pcUsedStage)1577 PushConstantGraphicsOverlapTest::PushConstantGraphicsOverlapTest(
1578     tcu::TestContext &testContext, const std::string &name, const PipelineConstructionType pipelineConstructionType,
1579     const uint32_t rangeCount, const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const bool pushConstant2,
1580     const PushConstantUseStage pcUsedStage)
1581     : PushConstantGraphicsTest(testContext, name, pipelineConstructionType, rangeCount, pushConstantRange, false,
1582                                INDEX_TYPE_CONST_LITERAL, pushConstant2, pcUsedStage)
1583 {
1584 }
1585 
~PushConstantGraphicsOverlapTest(void)1586 PushConstantGraphicsOverlapTest::~PushConstantGraphicsOverlapTest(void)
1587 {
1588 }
1589 
getPushConstantDeclarationStr(VkShaderStageFlags shaderStage) const1590 std::string PushConstantGraphicsOverlapTest::getPushConstantDeclarationStr(VkShaderStageFlags shaderStage) const
1591 {
1592     std::stringstream src;
1593 
1594     src << "layout(push_constant) uniform Material\n"
1595         << "{\n";
1596 
1597     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1598     {
1599         if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStage)
1600         {
1601             switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1602             {
1603             case SIZE_CASE_4:
1604                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") float color;\n";
1605                 break;
1606             case SIZE_CASE_8:
1607                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec2 color;\n";
1608                 break;
1609             case SIZE_CASE_12:
1610                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec3 color;\n";
1611                 break;
1612             case SIZE_CASE_16:
1613                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color;\n";
1614                 break;
1615             case SIZE_CASE_32:
1616                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[2];\n";
1617                 break;
1618             case SIZE_CASE_36:
1619                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") int unused1;\n"
1620                     << "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 4) << ") vec4 unused2;\n"
1621                     << "    layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 20) << ") vec4 color;\n";
1622                 break;
1623             case SIZE_CASE_128:
1624                 src << "    layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[8];\n";
1625                 break;
1626             default:
1627                 DE_FATAL("Not implemented");
1628                 break;
1629             }
1630         }
1631     }
1632 
1633     src << "} matInst;\n";
1634 
1635     return src.str();
1636 }
1637 
getSwizzleStr(uint32_t size)1638 std::string getSwizzleStr(uint32_t size)
1639 {
1640     switch (size)
1641     {
1642     case 4:
1643         return ".x";
1644     case 8:
1645         return ".xy";
1646     case 12:
1647         return ".xyz";
1648     case 16:
1649     case 32:
1650     case 36:
1651     case 128:
1652         return "";
1653     default:
1654         DE_FATAL("Not implemented");
1655         return "";
1656     }
1657 }
1658 
getColorReadStr(uint32_t size)1659 std::string getColorReadStr(uint32_t size)
1660 {
1661     // Always read the last element from array types
1662     const std::string arrayNdx     = (size == 128u) ? "[7]" : (size == 32u) ? "[1]" : "";
1663     const std::string colorReadStr = getSwizzleStr(size) + " += matInst.color" + arrayNdx + ";\n";
1664 
1665     return colorReadStr;
1666 }
1667 
initPrograms(SourceCollections & sourceCollections) const1668 void PushConstantGraphicsOverlapTest::initPrograms(SourceCollections &sourceCollections) const
1669 {
1670     for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1671     {
1672         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1673         {
1674             const std::string source =
1675                 "#version 450\n"
1676                 "layout(location = 0) in highp vec4 position;\n"
1677                 "layout(location = 1) in highp vec4 inColor;\n"
1678                 "layout(location = 0) out highp vec4 vtxColor;\n"
1679                 "out gl_PerVertex\n"
1680                 "{\n"
1681                 "    vec4 gl_Position;\n"
1682                 "};\n" +
1683                 ((m_pcUsedStage & PC_USE_STAGE_VERTEX) ? getPushConstantDeclarationStr(VK_SHADER_STAGE_VERTEX_BIT) :
1684                                                          "\n") +
1685                 "void main()\n"
1686                 "{\n"
1687                 "    gl_Position = position;\n"
1688                 "    vec4 color = inColor;\n" +
1689                 ((m_pcUsedStage & PC_USE_STAGE_VERTEX) ?
1690                      "    color" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) :
1691                      "\n") +
1692                 "    vtxColor = color;\n"
1693                 "}\n";
1694 
1695             sourceCollections.glslSources.add("color_vert") << glu::VertexSource(source);
1696         }
1697 
1698         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1699         {
1700             const std::string source = "#version 450\n"
1701                                        "layout (vertices = 3) out;\n" +
1702                                        ((m_pcUsedStage & PC_USE_STAGE_TESC) ?
1703                                             getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) :
1704                                             "\n") +
1705                                        "layout(location = 0) in highp vec4 color[];\n"
1706                                        "layout(location = 0) out highp vec4 vtxColor[];\n"
1707                                        "in gl_PerVertex\n"
1708                                        "{\n"
1709                                        "    vec4 gl_Position;\n"
1710                                        "} gl_in[gl_MaxPatchVertices];\n"
1711                                        "out gl_PerVertex\n"
1712                                        "{\n"
1713                                        "    vec4 gl_Position;\n"
1714                                        "} gl_out[];\n"
1715                                        "void main()\n"
1716                                        "{\n"
1717                                        "    gl_TessLevelInner[0] = 2.0;\n"
1718                                        "    gl_TessLevelOuter[0] = 2.0;\n"
1719                                        "    gl_TessLevelOuter[1] = 2.0;\n"
1720                                        "    gl_TessLevelOuter[2] = 2.0;\n"
1721                                        "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1722                                        "    vec4 outColor = color[gl_InvocationID];\n" +
1723                                        ((m_pcUsedStage & PC_USE_STAGE_TESC) ?
1724                                             "    outColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) :
1725                                             "\n") +
1726                                        "    vtxColor[gl_InvocationID] = outColor;\n"
1727                                        "}\n";
1728 
1729             sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(source);
1730         }
1731 
1732         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1733         {
1734             const std::string source =
1735                 "#version 450\n"
1736                 "layout (triangles) in;\n" +
1737                 ((m_pcUsedStage & PC_USE_STAGE_TESE) ?
1738                      getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) :
1739                      "\n") +
1740                 "layout(location = 0) in highp vec4 color[];\n"
1741                 "layout(location = 0) out highp vec4 vtxColor;\n"
1742                 "in gl_PerVertex\n"
1743                 "{\n"
1744                 "    vec4 gl_Position;\n"
1745                 "} gl_in[gl_MaxPatchVertices];\n"
1746                 "out gl_PerVertex\n"
1747                 "{\n"
1748                 "    vec4 gl_Position;\n"
1749                 "};\n"
1750                 "void main()\n"
1751                 "{\n"
1752                 "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + "
1753                 "gl_TessCoord.z * gl_in[2].gl_Position;\n"
1754                 "    vtxColor = gl_TessCoord.x * color[0] + gl_TessCoord.y * color[1] + gl_TessCoord.z * color[2];\n" +
1755                 ((m_pcUsedStage & PC_USE_STAGE_TESE) ?
1756                      "    vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) :
1757                      "\n") +
1758                 "}\n";
1759 
1760             sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(source);
1761         }
1762 
1763         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1764         {
1765             const std::string source =
1766                 "#version 450\n"
1767                 "layout(triangles) in;\n"
1768                 "layout(triangle_strip, max_vertices=3) out;\n" +
1769                 ((m_pcUsedStage & PC_USE_STAGE_GEOM) ? getPushConstantDeclarationStr(VK_SHADER_STAGE_GEOMETRY_BIT) :
1770                                                        "\n") +
1771                 "layout(location = 0) in highp vec4 color[];\n"
1772                 "layout(location = 0) out highp vec4 vtxColor;\n"
1773                 "in gl_PerVertex\n"
1774                 "{\n"
1775                 "    vec4 gl_Position;\n"
1776                 "} gl_in[];\n"
1777                 "out gl_PerVertex\n"
1778                 "{\n"
1779                 "    vec4 gl_Position;\n"
1780                 "};\n"
1781                 "void main()\n"
1782                 "{\n"
1783                 "    for(int i = 0; i < 3; i++)\n"
1784                 "    {\n"
1785                 "        gl_Position.xyz = gl_in[i].gl_Position.xyz" +
1786                 ((m_pcUsedStage & PC_USE_STAGE_GEOM) ? "/2.0;\n" : ";\n") +
1787                 "        gl_Position.w = gl_in[i].gl_Position.w;\n"
1788                 "        vtxColor = color[i];\n" +
1789                 ((m_pcUsedStage & PC_USE_STAGE_GEOM) ?
1790                      "        vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) :
1791                      "\n") +
1792                 "        EmitVertex();\n"
1793                 "    }\n"
1794                 "    EndPrimitive();\n"
1795                 "}\n";
1796 
1797             sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(source);
1798         }
1799 
1800         if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1801         {
1802             const std::string source =
1803                 "#version 450\n"
1804                 "layout(location = 0) in highp vec4 vtxColor;\n"
1805                 "layout(location = 0) out highp vec4 fragColor;\n" +
1806                 ((m_pcUsedStage & PC_USE_STAGE_FRAG) ? getPushConstantDeclarationStr(VK_SHADER_STAGE_FRAGMENT_BIT) :
1807                                                        "\n") +
1808                 "void main (void)\n"
1809                 "{\n"
1810                 "    fragColor = vtxColor;\n" +
1811                 ((m_pcUsedStage & PC_USE_STAGE_FRAG) ?
1812                      "    fragColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) :
1813                      "\n") +
1814                 "    fragColor = min(mod(fragColor, 2.0), 2.0 - mod(fragColor, 2.0));\n"
1815                 "}\n";
1816 
1817             sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(source);
1818         }
1819     }
1820 }
1821 
createInstance(Context & context) const1822 TestInstance *PushConstantGraphicsOverlapTest::createInstance(Context &context) const
1823 {
1824     return new PushConstantGraphicsOverlapTestInstance(context, m_pipelineConstructionType, m_rangeCount,
1825                                                        m_pushConstantRange, false, INDEX_TYPE_CONST_LITERAL,
1826                                                        m_pushConstant2, m_pcUsedStage);
1827 }
1828 
1829 class PushConstantComputeTest : public vkt::TestCase
1830 {
1831 public:
1832     PushConstantComputeTest(tcu::TestContext &testContext, const std::string &name, const ComputeTestType testType,
1833                             const PushConstantData pushConstantRange);
1834     virtual ~PushConstantComputeTest(void);
1835     virtual void initPrograms(SourceCollections &sourceCollections) const;
1836     virtual TestInstance *createInstance(Context &context) const;
1837     virtual void checkSupport(Context &context) const;
1838 
1839 private:
1840     const ComputeTestType m_testType;
1841     const PushConstantData m_pushConstantRange;
1842 };
1843 
1844 class PushConstantComputeTestInstance : public vkt::TestInstance
1845 {
1846 public:
1847     PushConstantComputeTestInstance(Context &context, const ComputeTestType testType,
1848                                     const PushConstantData pushConstantRange);
1849     virtual ~PushConstantComputeTestInstance(void);
1850     virtual tcu::TestStatus iterate(void);
1851 
1852 private:
1853     const ComputeTestType m_testType;
1854     const PushConstantData m_pushConstantRange;
1855 
1856     Move<VkBuffer> m_outBuffer;
1857     de::MovePtr<Allocation> m_outBufferAlloc;
1858     Move<VkDescriptorPool> m_descriptorPool;
1859     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1860     Move<VkDescriptorSet> m_descriptorSet;
1861 
1862     Move<VkPipelineLayout> m_pipelineLayout;
1863     Move<VkPipeline> m_computePipelines;
1864 
1865     Move<VkShaderModule> m_computeShaderModule;
1866 
1867     Move<VkCommandPool> m_cmdPool;
1868     Move<VkCommandBuffer> m_cmdBuffer;
1869 };
1870 
PushConstantComputeTest(tcu::TestContext & testContext,const std::string & name,const ComputeTestType testType,const PushConstantData pushConstantRange)1871 PushConstantComputeTest::PushConstantComputeTest(tcu::TestContext &testContext, const std::string &name,
1872                                                  const ComputeTestType testType,
1873                                                  const PushConstantData pushConstantRange)
1874     : vkt::TestCase(testContext, name)
1875     , m_testType(testType)
1876     , m_pushConstantRange(pushConstantRange)
1877 {
1878 }
1879 
~PushConstantComputeTest(void)1880 PushConstantComputeTest::~PushConstantComputeTest(void)
1881 {
1882 }
1883 
createInstance(Context & context) const1884 TestInstance *PushConstantComputeTest::createInstance(Context &context) const
1885 {
1886     return new PushConstantComputeTestInstance(context, m_testType, m_pushConstantRange);
1887 }
1888 
checkSupport(Context & context) const1889 void PushConstantComputeTest::checkSupport(Context &context) const
1890 {
1891     if (CTT_UNINITIALIZED == m_testType)
1892         context.requireDeviceFunctionality("VK_KHR_maintenance4");
1893 }
1894 
initPrograms(SourceCollections & sourceCollections) const1895 void PushConstantComputeTest::initPrograms(SourceCollections &sourceCollections) const
1896 {
1897     std::ostringstream computeSrc;
1898 
1899     computeSrc << "#version 450\n"
1900                << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1901                << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1902                << "  vec4 elements[];\n"
1903                << "} outData;\n"
1904                << "layout(push_constant) uniform Material{\n"
1905                << "  vec4 element;\n"
1906                << "} matInst;\n"
1907                << "void main (void)\n"
1908                << "{\n"
1909                << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1910                << "}\n";
1911 
1912     sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1913 }
1914 
PushConstantComputeTestInstance(Context & context,const ComputeTestType testType,const PushConstantData pushConstantRange)1915 PushConstantComputeTestInstance::PushConstantComputeTestInstance(Context &context, const ComputeTestType testType,
1916                                                                  const PushConstantData pushConstantRange)
1917     : vkt::TestInstance(context)
1918     , m_testType(testType)
1919     , m_pushConstantRange(pushConstantRange)
1920 {
1921     const DeviceInterface &vk       = context.getDeviceInterface();
1922     const VkDevice vkDevice         = context.getDevice();
1923     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1924     SimpleAllocator memAlloc(
1925         vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1926 
1927     // Create pipeline layout
1928     {
1929         // create push constant range
1930         VkPushConstantRange pushConstantRanges;
1931         pushConstantRanges.stageFlags = m_pushConstantRange.range.shaderStage;
1932         pushConstantRanges.offset     = m_pushConstantRange.range.offset;
1933         pushConstantRanges.size       = m_pushConstantRange.range.size;
1934 
1935         // create descriptor set layout
1936         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
1937                                     .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
1938                                     .build(vk, vkDevice);
1939 
1940         // create descriptor pool
1941         m_descriptorPool = DescriptorPoolBuilder()
1942                                .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
1943                                .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1944 
1945         // create uniform buffer
1946         const VkDeviceSize bufferSize             = sizeof(tcu::Vec4) * 8;
1947         const VkBufferCreateInfo bufferCreateInfo = {
1948             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1949             DE_NULL,                              // const void* pNext;
1950             0u,                                   // VkBufferCreateFlags    flags
1951             bufferSize,                           // VkDeviceSize size;
1952             VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // VkBufferUsageFlags usage;
1953             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1954             1u,                                   // uint32_t queueFamilyCount;
1955             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
1956         };
1957 
1958         m_outBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1959         m_outBufferAlloc =
1960             memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1961         VK_CHECK(
1962             vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1963 
1964         // create and update descriptor set
1965         const VkDescriptorSetAllocateInfo allocInfo = {
1966             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                             sType;
1967             DE_NULL,                                        // const void*                                 pNext;
1968             *m_descriptorPool,         // VkDescriptorPool                            descriptorPool;
1969             1u,                        // uint32_t                                    setLayoutCount;
1970             &(*m_descriptorSetLayout), // const VkDescriptorSetLayout*                pSetLayouts;
1971         };
1972         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1973 
1974         const VkDescriptorBufferInfo descriptorInfo =
1975             makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1976 
1977         DescriptorSetUpdateBuilder()
1978             .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1979                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1980             .update(vk, vkDevice);
1981 
1982         // create pipeline layout
1983         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1984             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1985             DE_NULL,                                       // const void* pNext;
1986             0u,                                            // VkPipelineLayoutCreateFlags flags;
1987             1u,                                            // uint32_t descriptorSetCount;
1988             &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
1989             1u,                                            // uint32_t pushConstantRangeCount;
1990             &pushConstantRanges                            // const VkPushConstantRange* pPushConstantRanges;
1991         };
1992 
1993         m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1994     }
1995 
1996     // create pipeline
1997     {
1998         m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1999 
2000         const VkPipelineShaderStageCreateInfo stageCreateInfo = {
2001             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2002             DE_NULL,                                             // const void* pNext;
2003             0u,                                                  // VkPipelineShaderStageCreateFlags flags;
2004             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
2005             *m_computeShaderModule,                              // VkShaderModule module;
2006             "main",                                              // const char* pName;
2007             DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
2008         };
2009 
2010         const VkComputePipelineCreateInfo createInfo = {
2011             VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                             sType;
2012             DE_NULL,                                        // const void*                                 pNext;
2013             0u,                                             // VkPipelineCreateFlags                       flags;
2014             stageCreateInfo,                                // VkPipelineShaderStageCreateInfo             stage;
2015             *m_pipelineLayout,                              // VkPipelineLayout                            layout;
2016             (VkPipeline)0, // VkPipeline                                  basePipelineHandle;
2017             0u,            // int32_t                                     basePipelineIndex;
2018         };
2019 
2020         m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
2021     }
2022 
2023     // Create command pool
2024     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2025 
2026     // Create command buffer
2027     {
2028         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2029 
2030         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2031 
2032         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
2033         vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1,
2034                                  &(*m_descriptorSet), 0, DE_NULL);
2035 
2036         // update push constant
2037         if (CTT_UNINITIALIZED != m_testType)
2038         {
2039             tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2040             vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage,
2041                                 m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
2042         }
2043 
2044         vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
2045 
2046         const VkBufferMemoryBarrier buf_barrier = {
2047             VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, //    VkStructureType    sType;
2048             DE_NULL,                                 //    const void*        pNext;
2049             VK_ACCESS_SHADER_WRITE_BIT,              //    VkAccessFlags      srcAccessMask;
2050             VK_ACCESS_HOST_READ_BIT,                 //    VkAccessFlags      dstAccessMask;
2051             VK_QUEUE_FAMILY_IGNORED,                 //    uint32_t           srcQueueFamilyIndex;
2052             VK_QUEUE_FAMILY_IGNORED,                 //    uint32_t           dstQueueFamilyIndex;
2053             *m_outBuffer,                            //    VkBuffer           buffer;
2054             0,                                       //    VkDeviceSize       offset;
2055             VK_WHOLE_SIZE                            //    VkDeviceSize       size;
2056         };
2057 
2058         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0,
2059                               DE_NULL, 1, &buf_barrier, 0, DE_NULL);
2060 
2061         endCommandBuffer(vk, *m_cmdBuffer);
2062     }
2063 }
2064 
~PushConstantComputeTestInstance(void)2065 PushConstantComputeTestInstance::~PushConstantComputeTestInstance(void)
2066 {
2067 }
2068 
iterate(void)2069 tcu::TestStatus PushConstantComputeTestInstance::iterate(void)
2070 {
2071     const DeviceInterface &vk = m_context.getDeviceInterface();
2072     const VkDevice vkDevice   = m_context.getDevice();
2073     const VkQueue queue       = m_context.getUniversalQueue();
2074 
2075     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2076 
2077     // The test should run without crashing when reading that undefined value.
2078     // The actual value is not important, test just shouldn't crash.
2079     if (CTT_UNINITIALIZED == m_testType)
2080         return tcu::TestStatus::pass("pass");
2081 
2082     invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
2083 
2084     // verify result
2085     std::vector<tcu::Vec4> expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
2086     if (deMemCmp((void *)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
2087     {
2088         return tcu::TestStatus::fail("Image mismatch");
2089     }
2090     return tcu::TestStatus::pass("result image matches with reference");
2091 }
2092 
2093 class PushConstantLifetimeTest : public vkt::TestCase
2094 {
2095 public:
2096     PushConstantLifetimeTest(tcu::TestContext &testContext, const std::string &name,
2097                              const PipelineConstructionType pipelineConstructionType,
2098                              const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
2099                              const std::vector<CommandData> &cmdList);
2100 
2101     virtual ~PushConstantLifetimeTest(void);
2102 
2103     virtual void checkSupport(Context &context) const;
2104 
2105     virtual void initPrograms(SourceCollections &sourceCollections) const;
2106 
2107     virtual TestInstance *createInstance(Context &context) const;
2108 
2109 private:
2110     const PipelineConstructionType m_pipelineConstructionType;
2111     PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
2112     std::vector<CommandData> m_cmdList;
2113 };
2114 
2115 class PushConstantLifetimeTestInstance : public vkt::TestInstance
2116 {
2117 public:
2118     PushConstantLifetimeTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
2119                                      const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
2120                                      const std::vector<CommandData> &cmdList);
2121 
2122     virtual ~PushConstantLifetimeTestInstance(void);
2123 
2124     virtual tcu::TestStatus iterate(void);
2125 
2126     void init(void);
2127 
2128     tcu::TestStatus verify(bool verifyGraphics, bool verifyCompute);
2129 
2130 private:
2131     PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
2132     PipelineConstructionType m_pipelineConstructionType;
2133     std::vector<CommandData> m_cmdList;
2134 
2135     std::vector<Vertex4RGBA> m_vertices;
2136 
2137     const tcu::UVec2 m_renderSize;
2138     const VkFormat m_colorFormat;
2139 
2140     VkImageCreateInfo m_colorImageCreateInfo;
2141     Move<VkImage> m_colorImage;
2142     de::MovePtr<Allocation> m_colorImageAlloc;
2143     Move<VkImageView> m_colorAttachmentView;
2144     RenderPassWrapper m_renderPass;
2145     Move<VkFramebuffer> m_framebuffer;
2146 
2147     ShaderWrapper m_vertexShaderModule;
2148     ShaderWrapper m_fragmentShaderModule;
2149     ShaderWrapper m_computeShaderModule;
2150 
2151     std::vector<VkPipelineShaderStageCreateInfo> m_shaderStage;
2152 
2153     Move<VkBuffer> m_vertexBuffer;
2154     de::MovePtr<Allocation> m_vertexBufferAlloc;
2155 
2156     Move<VkBuffer> m_outBuffer;
2157     de::MovePtr<Allocation> m_outBufferAlloc;
2158     Move<VkDescriptorPool> m_descriptorPool;
2159     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2160     Move<VkDescriptorSet> m_descriptorSet;
2161 
2162     PipelineLayoutWrapper m_pipelineLayout[3];
2163     GraphicsPipelineWrapper m_graphicsPipeline[3];
2164     Move<VkPipeline> m_computePipeline[3];
2165 
2166     Move<VkCommandPool> m_cmdPool;
2167     Move<VkCommandBuffer> m_cmdBuffer;
2168 };
2169 
PushConstantLifetimeTest(tcu::TestContext & testContext,const std::string & name,const PipelineConstructionType pipelineConstructionType,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const std::vector<CommandData> & cmdList)2170 PushConstantLifetimeTest::PushConstantLifetimeTest(tcu::TestContext &testContext, const std::string &name,
2171                                                    const PipelineConstructionType pipelineConstructionType,
2172                                                    const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
2173                                                    const std::vector<CommandData> &cmdList)
2174     : vkt::TestCase(testContext, name)
2175     , m_pipelineConstructionType(pipelineConstructionType)
2176     , m_cmdList(cmdList)
2177 {
2178     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
2179 }
2180 
~PushConstantLifetimeTest(void)2181 PushConstantLifetimeTest::~PushConstantLifetimeTest(void)
2182 {
2183 }
2184 
checkSupport(Context & context) const2185 void PushConstantLifetimeTest::checkSupport(Context &context) const
2186 {
2187     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
2188                                           m_pipelineConstructionType);
2189 }
2190 
initPrograms(SourceCollections & sourceCollections) const2191 void PushConstantLifetimeTest::initPrograms(SourceCollections &sourceCollections) const
2192 {
2193     std::ostringstream vertexSrc;
2194 
2195     vertexSrc << "#version 450\n"
2196               << "layout(location = 0) in highp vec4 position;\n"
2197               << "layout(location = 1) in highp vec4 inColor;\n"
2198               << "layout(location = 0) out highp vec4 vtxColor;\n"
2199               << "out gl_PerVertex\n"
2200               << "{\n"
2201               << "  vec4 gl_Position;\n"
2202               << "};\n"
2203               << "layout(push_constant) uniform Material {\n"
2204               << "    layout(offset = 16) vec4 color;\n"
2205               << "}matInst;\n"
2206               << "void main()\n"
2207               << "{\n"
2208               << "    gl_Position = position;\n"
2209               << "    vtxColor = vec4(inColor.x + matInst.color.x,\n"
2210               << "                    inColor.y - matInst.color.y,\n"
2211               << "                    inColor.z + matInst.color.z,\n"
2212               << "                    inColor.w + matInst.color.w);\n"
2213               << "}\n";
2214 
2215     sourceCollections.glslSources.add("color_vert_lt") << glu::VertexSource(vertexSrc.str());
2216 
2217     std::ostringstream fragmentSrc;
2218 
2219     fragmentSrc << "#version 450\n"
2220                 << "layout(location = 0) in highp vec4 vtxColor;\n"
2221                 << "layout(location = 0) out highp vec4 fragColor;\n"
2222                 << "void main (void)\n"
2223                 << "{\n"
2224                 << "    fragColor = vtxColor;\n"
2225                 << "}\n";
2226 
2227     sourceCollections.glslSources.add("color_frag_lt") << glu::FragmentSource(fragmentSrc.str());
2228 
2229     std::ostringstream computeSrc;
2230 
2231     computeSrc << "#version 450\n"
2232                << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2233                << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
2234                << "  vec4 elements[];\n"
2235                << "} outData;\n"
2236                << "layout(push_constant) uniform Material{\n"
2237                << "    layout(offset = 16) vec4 element;\n"
2238                << "} matInst;\n"
2239                << "void main (void)\n"
2240                << "{\n"
2241                << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
2242                << "}\n";
2243 
2244     sourceCollections.glslSources.add("compute_lt") << glu::ComputeSource(computeSrc.str());
2245 }
2246 
createInstance(Context & context) const2247 TestInstance *PushConstantLifetimeTest::createInstance(Context &context) const
2248 {
2249     return new PushConstantLifetimeTestInstance(context, m_pipelineConstructionType, m_pushConstantRange, m_cmdList);
2250 }
2251 
PushConstantLifetimeTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],const std::vector<CommandData> & cmdList)2252 PushConstantLifetimeTestInstance::PushConstantLifetimeTestInstance(
2253     Context &context, const PipelineConstructionType pipelineConstructionType,
2254     const PushConstantData pushConstantRange[MAX_RANGE_COUNT], const std::vector<CommandData> &cmdList)
2255     : vkt::TestInstance(context)
2256     , m_pipelineConstructionType(pipelineConstructionType)
2257     , m_cmdList(cmdList)
2258     , m_renderSize(32, 32)
2259     , m_colorFormat(VK_FORMAT_R8G8B8A8_UNORM)
2260     , m_graphicsPipeline{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
2261                           context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
2262                          {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
2263                           context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
2264                          {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
2265                           context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType}}
2266 {
2267     deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
2268 }
2269 
init(void)2270 void PushConstantLifetimeTestInstance::init(void)
2271 {
2272     const DeviceInterface &vk       = m_context.getDeviceInterface();
2273     const VkDevice vkDevice         = m_context.getDevice();
2274     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2275     SimpleAllocator memAlloc(
2276         vk, vkDevice,
2277         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2278     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
2279                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
2280 
2281     // Create color image
2282     {
2283         const VkImageCreateInfo colorImageParams = {
2284             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
2285             DE_NULL,                                                               // const void* pNext;
2286             0u,                                                                    // VkImageCreateFlags flags;
2287             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
2288             m_colorFormat,                                                         // VkFormat format;
2289             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
2290             1u,                                                                    // uint32_t mipLevels;
2291             1u,                                                                    // uint32_t arrayLayers;
2292             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
2293             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
2294             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
2295             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
2296             1u,                                                                    // uint32_t queueFamilyIndexCount;
2297             &queueFamilyIndex,         // const uint32_t* pQueueFamilyIndices;
2298             VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
2299         };
2300 
2301         m_colorImageCreateInfo = colorImageParams;
2302         m_colorImage           = createImage(vk, vkDevice, &m_colorImageCreateInfo);
2303 
2304         // Allocate and bind color image memory
2305         m_colorImageAlloc =
2306             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
2307         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
2308                                     m_colorImageAlloc->getOffset()));
2309     }
2310 
2311     // Create color attachment view
2312     {
2313         const VkImageViewCreateInfo colorAttachmentViewParams = {
2314             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,    // VkStructureType sType;
2315             DE_NULL,                                     // const void* pNext;
2316             0u,                                          // VkImageViewCreateFlags flags;
2317             *m_colorImage,                               // VkImage image;
2318             VK_IMAGE_VIEW_TYPE_2D,                       // VkImageViewType viewType;
2319             m_colorFormat,                               // VkFormat format;
2320             componentMappingRGBA,                        // VkChannelMapping channels;
2321             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}, // VkImageSubresourceRange subresourceRange;
2322         };
2323 
2324         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
2325     }
2326 
2327     // Create render pass
2328     m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, m_colorFormat);
2329 
2330     // Create framebuffer
2331     {
2332         const VkImageView attachmentBindInfos[1] = {*m_colorAttachmentView};
2333 
2334         const VkFramebufferCreateInfo framebufferParams = {
2335             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
2336             DE_NULL,                                   // const void* pNext;
2337             0u,                                        // VkFramebufferCreateFlags flags;
2338             *m_renderPass,                             // VkRenderPass renderPass;
2339             1u,                                        // uint32_t attachmentCount;
2340             attachmentBindInfos,                       // const VkImageView* pAttachments;
2341             (uint32_t)m_renderSize.x(),                // uint32_t width;
2342             (uint32_t)m_renderSize.y(),                // uint32_t height;
2343             1u                                         // uint32_t layers;
2344         };
2345 
2346         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, *m_colorImage);
2347     }
2348 
2349     // Create data for pipeline layout
2350     {
2351         // create descriptor set layout
2352         m_descriptorSetLayout = DescriptorSetLayoutBuilder()
2353                                     .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
2354                                     .build(vk, vkDevice);
2355 
2356         // create descriptor pool
2357         m_descriptorPool = DescriptorPoolBuilder()
2358                                .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
2359                                .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2360 
2361         // create storage buffer
2362         const VkDeviceSize bufferSize             = sizeof(tcu::Vec4) * 8;
2363         const VkBufferCreateInfo bufferCreateInfo = {
2364             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
2365             DE_NULL,                              // const void* pNext;
2366             0u,                                   // VkBufferCreateFlags                flags
2367             bufferSize,                           // VkDeviceSize size;
2368             VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,   // VkBufferUsageFlags usage;
2369             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
2370             1u,                                   // uint32_t queueFamilyCount;
2371             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
2372         };
2373 
2374         m_outBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
2375         m_outBufferAlloc =
2376             memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
2377         VK_CHECK(
2378             vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
2379 
2380         // create and update descriptor set
2381         const VkDescriptorSetAllocateInfo allocInfo = {
2382             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
2383             DE_NULL,                                        // const void* pNext;
2384             *m_descriptorPool,                              // VkDescriptorPool descriptorPool;
2385             1u,                                             // uint32_t setLayoutCount;
2386             &(*m_descriptorSetLayout),                      // const VkDescriptorSetLayout* pSetLayouts;
2387         };
2388         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
2389 
2390         const VkDescriptorBufferInfo descriptorInfo =
2391             makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
2392 
2393         DescriptorSetUpdateBuilder()
2394             .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
2395                          VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
2396             .update(vk, vkDevice);
2397 
2398         // create push constant ranges
2399         const VkPushConstantRange pushConstantRanges[]{
2400             {m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset,
2401              m_pushConstantRange[0].range.size},
2402             {m_pushConstantRange[1].range.shaderStage, m_pushConstantRange[1].range.offset,
2403              m_pushConstantRange[1].range.size}};
2404 
2405         const VkPipelineLayoutCreateInfo pipelineLayoutParams[]{
2406             {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2407              DE_NULL,                                       // const void* pNext;
2408              0u,                                            // VkPipelineLayoutCreateFlags flags;
2409              1u,                                            // uint32_t descriptorSetCount;
2410              &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
2411              1u,                                            // uint32_t pushConstantRangeCount;
2412              &(pushConstantRanges[0])},
2413             {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
2414              DE_NULL,                                       // const void* pNext;
2415              0u,                                            // VkPipelineLayoutCreateFlags flags;
2416              1u,                                            // uint32_t descriptorSetCount;
2417              &(*m_descriptorSetLayout),                     // const VkDescriptorSetLayout* pSetLayouts;
2418              1u,                                            // uint32_t pushConstantRangeCount;
2419              &(pushConstantRanges[1])}};
2420 
2421         m_pipelineLayout[0] =
2422             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &(pipelineLayoutParams[0]));
2423         m_pipelineLayout[1] =
2424             PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &(pipelineLayoutParams[1]));
2425     }
2426 
2427     m_vertexShaderModule   = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert_lt"), 0);
2428     m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_lt"), 0);
2429 
2430     // Create graphics pipelines
2431     {
2432         const VkVertexInputBindingDescription vertexInputBindingDescription{
2433             0u,                         // uint32_t binding;
2434             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
2435             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
2436         };
2437 
2438         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[]{
2439             {
2440                 0u,                            // uint32_t location;
2441                 0u,                            // uint32_t binding;
2442                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2443                 0u                             // uint32_t offsetInBytes;
2444             },
2445             {
2446                 1u,                            // uint32_t location;
2447                 0u,                            // uint32_t binding;
2448                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
2449                 offsetof(Vertex4RGBA, color),  // uint32_t offset;
2450             }};
2451 
2452         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
2453             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
2454             DE_NULL,                                                   // const void* pNext;
2455             0u,                                                        // vkPipelineVertexInputStateCreateFlags flags;
2456             1u,                                                        // uint32_t bindingCount;
2457             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
2458             2u,                              // uint32_t attributeCount;
2459             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
2460         };
2461 
2462         const VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
2463 
2464         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
2465         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
2466 
2467         m_graphicsPipeline[0]
2468             .setDefaultRasterizationState()
2469             .setDefaultDepthStencilState()
2470             .setDefaultMultisampleState()
2471             .setDefaultColorBlendState()
2472             .setDefaultTopology(topology)
2473             .setupVertexInputState(&vertexInputStateParams)
2474             .setupPreRasterizationShaderState(viewports, scissors, (m_pipelineLayout[0]), *m_renderPass, 0u,
2475                                               m_vertexShaderModule)
2476             .setupFragmentShaderState((m_pipelineLayout[0]), *m_renderPass, 0u, m_fragmentShaderModule)
2477             .setupFragmentOutputState(*m_renderPass)
2478             .setMonolithicPipelineLayout((m_pipelineLayout[0]))
2479             .buildPipeline();
2480 
2481         m_graphicsPipeline[1]
2482             .setDefaultRasterizationState()
2483             .setDefaultDepthStencilState()
2484             .setDefaultMultisampleState()
2485             .setDefaultColorBlendState()
2486             .setDefaultTopology(topology)
2487             .setupVertexInputState(&vertexInputStateParams)
2488             .setupPreRasterizationShaderState(viewports, scissors, (m_pipelineLayout[1]), *m_renderPass, 0u,
2489                                               m_vertexShaderModule)
2490             .setupFragmentShaderState((m_pipelineLayout[1]), *m_renderPass, 0u, m_fragmentShaderModule)
2491             .setupFragmentOutputState(*m_renderPass)
2492             .setMonolithicPipelineLayout((m_pipelineLayout[1]))
2493             .buildPipeline();
2494     }
2495 
2496     // Create vertex buffer
2497     {
2498         m_vertices = createQuad(1.0f, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
2499 
2500         const VkBufferCreateInfo vertexBufferParams = {
2501             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                    // VkStructureType sType;
2502             DE_NULL,                                                 // const void* pNext;
2503             0u,                                                      // VkBufferCreateFlags flags;
2504             (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
2505             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                       // VkBufferUsageFlags usage;
2506             VK_SHARING_MODE_EXCLUSIVE,                               // VkSharingMode sharingMode;
2507             1u,                                                      // uint32_t queueFamilyCount;
2508             &queueFamilyIndex                                        // const uint32_t* pQueueFamilyIndices;
2509         };
2510 
2511         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
2512         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
2513                                                 MemoryRequirement::HostVisible);
2514 
2515         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
2516                                      m_vertexBufferAlloc->getOffset()));
2517 
2518         // Load vertices into vertex buffer
2519         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
2520         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
2521     }
2522 
2523     // Create compute pipelines
2524     {
2525         m_computeShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("compute_lt"), 0);
2526 
2527         const VkPipelineShaderStageCreateInfo stageCreateInfo = {
2528             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
2529             DE_NULL,                                             // const void* pNext;
2530             0u,                                                  // VkPipelineShaderStageCreateFlags flags;
2531             VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits stage;
2532             m_computeShaderModule.getModule(),                   // VkShaderModule module;
2533             "main",                                              // const char* pName;
2534             DE_NULL                                              // const VkSpecializationInfo* pSpecializationInfo;
2535         };
2536 
2537         if (m_pushConstantRange[0].range.shaderStage & VK_SHADER_STAGE_COMPUTE_BIT)
2538         {
2539             const VkComputePipelineCreateInfo computePipelineLayoutParams = {
2540                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2541                 DE_NULL,                                        // const void* pNext;
2542                 0u,                                             // VkPipelineCreateFlags flags;
2543                 stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
2544                 *m_pipelineLayout[0],                           // VkPipelineLayout layout;
2545                 (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
2546                 0u,                                             // int32_t basePipelineIndex;
2547             };
2548 
2549             m_computePipeline[0] =
2550                 createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &computePipelineLayoutParams);
2551         }
2552         if (m_pushConstantRange[1].range.shaderStage & VK_SHADER_STAGE_COMPUTE_BIT)
2553         {
2554             const VkComputePipelineCreateInfo computePipelineLayoutParams = {
2555                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
2556                 DE_NULL,                                        // const void* pNext;
2557                 0u,                                             // VkPipelineCreateFlags flags;
2558                 stageCreateInfo,                                // VkPipelineShaderStageCreateInfo stage;
2559                 *m_pipelineLayout[1],                           // VkPipelineLayout layout;
2560                 (VkPipeline)0,                                  // VkPipeline basePipelineHandle;
2561                 0u,                                             // int32_t basePipelineIndex;
2562             };
2563 
2564             m_computePipeline[1] =
2565                 createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &computePipelineLayoutParams);
2566         }
2567     }
2568 }
2569 
~PushConstantLifetimeTestInstance(void)2570 PushConstantLifetimeTestInstance::~PushConstantLifetimeTestInstance(void)
2571 {
2572 }
2573 
iterate(void)2574 tcu::TestStatus PushConstantLifetimeTestInstance::iterate(void)
2575 {
2576     const DeviceInterface &vk       = m_context.getDeviceInterface();
2577     const VkDevice vkDevice         = m_context.getDevice();
2578     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2579     const VkQueue queue             = m_context.getUniversalQueue();
2580 
2581     bool verifyGraphics = false;
2582     bool verifyCompute  = false;
2583 
2584     init();
2585 
2586     // Create command pool
2587     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2588 
2589     // Create command buffer
2590     {
2591         const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
2592 
2593         // Set push constant value
2594         tcu::Vec4 value[2] = {{0.25f, 0.75f, 0.75f, 1.0f}, {0.25f, 0.75f, 0.75f, 1.0f}};
2595 
2596         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2597 
2598         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2599 
2600         for (size_t ndx = 0; ndx < m_cmdList.size(); ndx++)
2601         {
2602             const VkPushConstantRange pushConstantRange{m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.shaderStage,
2603                                                         m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.offset,
2604                                                         m_pushConstantRange[m_cmdList[ndx].rangeNdx].range.size};
2605 
2606             switch (m_cmdList[ndx].cType)
2607             {
2608             case CMD_PUSH_CONSTANT:
2609             {
2610                 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout[m_cmdList[ndx].rangeNdx],
2611                                     pushConstantRange.stageFlags, pushConstantRange.offset, pushConstantRange.size,
2612                                     &value);
2613                 break;
2614             }
2615             case CMD_BIND_PIPELINE_COMPUTE:
2616             {
2617                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
2618                                          *m_pipelineLayout[m_cmdList[ndx].rangeNdx], 0, 1u, &(*m_descriptorSet), 0,
2619                                          DE_NULL);
2620 
2621                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE,
2622                                    *m_computePipeline[m_cmdList[ndx].rangeNdx]);
2623                 break;
2624             }
2625             case CMD_BIND_PIPELINE_GRAPHICS:
2626             {
2627                 m_graphicsPipeline[m_cmdList[ndx].rangeNdx].bind(*m_cmdBuffer);
2628                 break;
2629             }
2630             case CMD_DRAW:
2631             {
2632                 const VkDeviceSize bufferOffset = 0;
2633 
2634                 const VkImageMemoryBarrier prePassBarrier = {
2635                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType sType;
2636                     DE_NULL,                                    // const void* pNext;
2637                     0,                                          // VkAccessFlags srcAccessMask;
2638                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags dstAccessMask;
2639                     VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout oldLayout;
2640                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
2641                     VK_QUEUE_FAMILY_IGNORED,                    // uint32_t srcQueueFamilyIndex;
2642                     VK_QUEUE_FAMILY_IGNORED,                    // uint32_t dstQueueFamilyIndex;
2643                     *m_colorImage,                              // VkImage image;
2644                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
2645                 };
2646 
2647                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2648                                       VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1,
2649                                       &prePassBarrier);
2650 
2651                 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
2652                                    attachmentClearValue);
2653 
2654                 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &bufferOffset);
2655                 vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
2656 
2657                 m_renderPass.end(vk, *m_cmdBuffer);
2658 
2659                 const VkImageMemoryBarrier postPassBarrier = {
2660                     VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType sType;
2661                     DE_NULL,                                    // const void* pNext;
2662                     VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags srcAccessMask;
2663                     VK_ACCESS_TRANSFER_WRITE_BIT,               // VkAccessFlags dstAccessMask;
2664                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout oldLayout;
2665                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout newLayout;
2666                     VK_QUEUE_FAMILY_IGNORED,                    // uint32_t srcQueueFamilyIndex;
2667                     VK_QUEUE_FAMILY_IGNORED,                    // uint32_t dstQueueFamilyIndex;
2668                     *m_colorImage,                              // VkImage image;
2669                     {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
2670                 };
2671 
2672                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2673                                       0, 0, DE_NULL, 0, DE_NULL, 1, &postPassBarrier);
2674 
2675                 verifyGraphics = true;
2676                 break;
2677             }
2678             case CMD_DISPATCH:
2679             {
2680 
2681                 vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
2682 
2683                 const VkBufferMemoryBarrier outputBarrier = {
2684                     VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
2685                     DE_NULL,                                 // const void* pNext;
2686                     VK_ACCESS_SHADER_WRITE_BIT,              // VkAccessFlags srcAccessMask;
2687                     VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
2688                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t srcQueueFamilyIndex;
2689                     VK_QUEUE_FAMILY_IGNORED,                 // uint32_t dstQueueFamilyIndex;
2690                     *m_outBuffer,                            // VkBuffer buffer;
2691                     0,                                       // VkDeviceSize offset;
2692                     VK_WHOLE_SIZE                            // VkDeviceSize size;
2693                 };
2694 
2695                 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0,
2696                                       0, DE_NULL, 1, &outputBarrier, 0, DE_NULL);
2697 
2698                 verifyCompute = true;
2699                 break;
2700             }
2701             case CMD_UNSUPPORTED:
2702                 break;
2703             default:
2704                 break;
2705             }
2706         }
2707 
2708         endCommandBuffer(vk, *m_cmdBuffer);
2709     }
2710 
2711     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2712 
2713     return verify(verifyGraphics, verifyCompute);
2714 }
2715 
verify(bool verifyGraphics,bool verifyCompute)2716 tcu::TestStatus PushConstantLifetimeTestInstance::verify(bool verifyGraphics, bool verifyCompute)
2717 {
2718     const DeviceInterface &vk = m_context.getDeviceInterface();
2719     const VkDevice vkDevice   = m_context.getDevice();
2720 
2721     const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
2722     const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
2723     const ColorVertexShader vertexShader;
2724     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuDepthFormat);
2725     const rr::Program program(&vertexShader, &fragmentShader);
2726     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
2727 
2728     bool graphicsOk = !verifyGraphics;
2729     bool computeOk  = !verifyCompute;
2730 
2731     // Compare result with reference image
2732     if (verifyGraphics)
2733     {
2734         // Render reference image
2735         {
2736             rr::RenderState renderState(refRenderer.getViewportState(),
2737                                         m_context.getDeviceProperties().limits.subPixelPrecisionBits);
2738             refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices);
2739         }
2740 
2741         const VkQueue queue             = m_context.getUniversalQueue();
2742         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2743         SimpleAllocator allocator(
2744             vk, vkDevice,
2745             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
2746         de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
2747                                                                     *m_colorImage, m_colorFormat, m_renderSize);
2748 
2749         graphicsOk = tcu::intThresholdPositionDeviationCompare(
2750             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
2751             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
2752     }
2753 
2754     // Compare compute output
2755     if (verifyCompute)
2756     {
2757         invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
2758 
2759         // verify result
2760         std::vector<tcu::Vec4> expectValue(8, tcu::Vec4(0.25f, 0.75f, 0.75f, 1.0f));
2761         if (deMemCmp((void *)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
2762             computeOk = false;
2763         else
2764             computeOk = true;
2765     }
2766 
2767     if (!graphicsOk)
2768         return tcu::TestStatus::fail("Image mismatch");
2769 
2770     if (!computeOk)
2771         return tcu::TestStatus::fail("Wrong output value");
2772 
2773     return tcu::TestStatus::pass("Result image matches reference");
2774 }
2775 
2776 // The overwrite-values cases will use a 2x2 storage image and 4 separate draws or dispatches to store the color of each pixel in
2777 // the image. The color will be calculated as baseColor*multiplier+colorOffset, and the base color, multiplier, color component
2778 // offsets and coords will be changed with multiple push commands before each draw/dispatch, to verify overwriting multiple ranges
2779 // works as expected.
2780 
2781 struct OverwritePushConstants
2782 {
2783     tcu::IVec4 coords; // We will only use the first two components, but an IVec4 eases matching alignments.
2784     tcu::UVec4 baseColor;
2785     tcu::UVec4 multiplier;
2786     uint32_t colorOffsets[4];
2787     tcu::UVec4 transparentGreen;
2788 };
2789 
2790 struct OverwriteTestParams
2791 {
2792     PipelineConstructionType pipelineConstructionType;
2793     OverwritePushConstants pushConstantValues[4];
2794     VkPipelineBindPoint bindPoint;
2795 };
2796 
2797 class OverwriteTestCase : public vkt::TestCase
2798 {
2799 public:
2800     OverwriteTestCase(tcu::TestContext &testCtx, const std::string &name, const OverwriteTestParams &params);
~OverwriteTestCase(void)2801     virtual ~OverwriteTestCase(void)
2802     {
2803     }
2804 
2805     virtual void checkSupport(Context &context) const;
2806     virtual void initPrograms(vk::SourceCollections &programCollection) const;
2807     virtual TestInstance *createInstance(Context &context) const;
2808 
2809 protected:
2810     OverwriteTestParams m_params;
2811 };
2812 
2813 class OverwriteTestInstance : public vkt::TestInstance
2814 {
2815 public:
2816     OverwriteTestInstance(Context &context, const OverwriteTestParams &params);
~OverwriteTestInstance(void)2817     virtual ~OverwriteTestInstance(void)
2818     {
2819     }
2820 
2821     virtual tcu::TestStatus iterate(void);
2822 
2823 protected:
2824     OverwriteTestParams m_params;
2825 };
2826 
OverwriteTestCase(tcu::TestContext & testCtx,const std::string & name,const OverwriteTestParams & params)2827 OverwriteTestCase::OverwriteTestCase(tcu::TestContext &testCtx, const std::string &name,
2828                                      const OverwriteTestParams &params)
2829     : vkt::TestCase(testCtx, name)
2830     , m_params(params)
2831 {
2832 }
2833 
checkSupport(Context & context) const2834 void OverwriteTestCase::checkSupport(Context &context) const
2835 {
2836     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
2837                                           m_params.pipelineConstructionType);
2838 }
2839 
initPrograms(vk::SourceCollections & programCollection) const2840 void OverwriteTestCase::initPrograms(vk::SourceCollections &programCollection) const
2841 {
2842     std::ostringstream shader;
2843 
2844     shader << "#version 450\n"
2845            << "layout (push_constant, std430) uniform PushConstants {\n"
2846            << "    ivec4   coords;\n" // Note we will only use the .xy swizzle.
2847            << "    uvec4   baseColor;\n"
2848            << "    uvec4   multiplier;\n"
2849            << "    uint    colorOffsets[4];\n"
2850            << "    uvec4   transparentGreen;\n"
2851            << "} pc;\n"
2852            << "layout(rgba8ui, set=0, binding=0) uniform uimage2D simage;\n"
2853            << "void main() {\n"
2854            << "    uvec4   colorOffsets = uvec4(pc.colorOffsets[0], pc.colorOffsets[1], pc.colorOffsets[2], "
2855               "pc.colorOffsets[3]);\n"
2856            << "    uvec4   finalColor   = pc.baseColor * pc.multiplier + colorOffsets + pc.transparentGreen;\n"
2857            << "    imageStore(simage, pc.coords.xy, finalColor);\n"
2858            << "}\n";
2859 
2860     if (m_params.bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE)
2861     {
2862         programCollection.glslSources.add("comp") << glu::ComputeSource(shader.str());
2863     }
2864     else if (m_params.bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS)
2865     {
2866         std::ostringstream vert;
2867         vert << "#version 450\n"
2868              << "\n"
2869              << "void main()\n"
2870              << "{\n"
2871              // Full-screen clockwise triangle strip with 4 vertices.
2872              << "    const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
2873              << "    const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
2874              << "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
2875              << "}\n";
2876 
2877         programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2878         programCollection.glslSources.add("frag") << glu::FragmentSource(shader.str());
2879     }
2880     else
2881         DE_ASSERT(false);
2882 }
2883 
createInstance(Context & context) const2884 TestInstance *OverwriteTestCase::createInstance(Context &context) const
2885 {
2886     return new OverwriteTestInstance(context, m_params);
2887 }
2888 
OverwriteTestInstance(Context & context,const OverwriteTestParams & params)2889 OverwriteTestInstance::OverwriteTestInstance(Context &context, const OverwriteTestParams &params)
2890     : vkt::TestInstance(context)
2891     , m_params(params)
2892 {
2893 }
2894 
iterate(void)2895 tcu::TestStatus OverwriteTestInstance::iterate(void)
2896 {
2897     const auto &vki       = m_context.getInstanceInterface();
2898     const auto &vkd       = m_context.getDeviceInterface();
2899     const auto physDevice = m_context.getPhysicalDevice();
2900     const auto device     = m_context.getDevice();
2901     auto &alloc           = m_context.getDefaultAllocator();
2902     const auto queue      = m_context.getUniversalQueue();
2903     const auto qIndex     = m_context.getUniversalQueueFamilyIndex();
2904     const bool isComp     = (m_params.bindPoint == VK_PIPELINE_BIND_POINT_COMPUTE);
2905 
2906     const VkShaderStageFlags stageFlags = (isComp ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT);
2907     const VkPipelineStageFlags writeStages =
2908         (isComp ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
2909     const auto imageFormat = VK_FORMAT_R8G8B8A8_UINT;
2910     const auto imageExtent = makeExtent3D(2u, 2u, 1u);
2911 
2912     // Storage image.
2913     const VkImageCreateInfo imageCreateInfo = {
2914         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                            // VkStructureType sType;
2915         nullptr,                                                        // const void* pNext;
2916         0u,                                                             // VkImageCreateFlags flags;
2917         VK_IMAGE_TYPE_2D,                                               // VkImageType imageType;
2918         imageFormat,                                                    // VkFormat format;
2919         imageExtent,                                                    // VkExtent3D extent;
2920         1u,                                                             // uint32_t mipLevels;
2921         1u,                                                             // uint32_t arrayLayers;
2922         VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits samples;
2923         VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling tiling;
2924         (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // VkImageUsageFlags usage;
2925         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode sharingMode;
2926         0u,                                                             // uint32_t queueFamilyIndexCount;
2927         nullptr,                                                        // const uint32_t* pQueueFamilyIndices;
2928         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout initialLayout;
2929     };
2930     ImageWithMemory storageImage(vkd, device, alloc, imageCreateInfo, MemoryRequirement::Any);
2931     const auto subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2932     const auto storageImageView =
2933         makeImageView(vkd, device, storageImage.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
2934 
2935     // Buffer to copy output pixels to.
2936     const auto tcuFormat  = mapVkFormat(imageFormat);
2937     const auto pixelSize  = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat));
2938     const auto bufferSize = pixelSize * imageExtent.width * imageExtent.height * imageExtent.depth;
2939 
2940     const auto bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2941     BufferWithMemory transferBuffer(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
2942 
2943     // Descriptor set layout and pipeline layout.
2944     DescriptorSetLayoutBuilder layoutBuilder;
2945     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags);
2946     const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
2947 
2948     const VkPushConstantRange pcRange = {
2949         stageFlags,                                            // VkShaderStageFlags stageFlags;
2950         0u,                                                    // uint32_t offset;
2951         static_cast<uint32_t>(sizeof(OverwritePushConstants)), // uint32_t size;
2952     };
2953     const PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, vkd, device, 1u,
2954                                                &descriptorSetLayout.get(), 1u, &pcRange);
2955 
2956     // Descriptor pool and set.
2957     DescriptorPoolBuilder poolBuilder;
2958     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
2959     const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2960     const auto descriptorSet  = makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
2961 
2962     DescriptorSetUpdateBuilder updateBuilder;
2963     const auto descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, storageImageView.get(), VK_IMAGE_LAYOUT_GENERAL);
2964     updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
2965                               VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo);
2966     updateBuilder.update(vkd, device);
2967 
2968     // Command pool and set.
2969     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
2970     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2971     const auto cmdBuffer    = cmdBufferPtr.get();
2972 
2973     // Pipeline.
2974     const std::vector<VkViewport> viewports(1, makeViewport(imageExtent));
2975     const std::vector<VkRect2D> scissors(1, makeRect2D(imageExtent));
2976 
2977     ShaderWrapper vertModule;
2978     ShaderWrapper fragModule;
2979     ShaderWrapper compModule;
2980 
2981     RenderPassWrapper renderPass;
2982     Move<VkFramebuffer> framebuffer;
2983     Move<VkPipeline> pipeline;
2984     GraphicsPipelineWrapper pipelineWrapper(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
2985                                             m_params.pipelineConstructionType);
2986 
2987     if (isComp)
2988     {
2989         compModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
2990         pipeline   = makeComputePipeline(vkd, device, pipelineLayout.get(), compModule.getModule());
2991     }
2992     else
2993     {
2994         vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
2995         fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
2996 
2997         const VkPipelineVertexInputStateCreateInfo inputState = {
2998             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType
2999             nullptr, // const void*                                 pNext
3000             0u,      // VkPipelineVertexInputStateCreateFlags       flags
3001             0u,      // uint32_t                                    vertexBindingDescriptionCount
3002             nullptr, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
3003             0u,      // uint32_t                                    vertexAttributeDescriptionCount
3004             nullptr, // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
3005         };
3006         renderPass = RenderPassWrapper(m_params.pipelineConstructionType, vkd, device);
3007         renderPass.createFramebuffer(vkd, device, 0u, DE_NULL, DE_NULL, imageExtent.width, imageExtent.height);
3008 
3009         const VkPipelineColorBlendStateCreateInfo colorBlendState{
3010             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
3011             DE_NULL,                 // const void*                                    pNext
3012             0u,                      // VkPipelineColorBlendStateCreateFlags            flags
3013             VK_FALSE,                // VkBool32                                        logicOpEnable
3014             VK_LOGIC_OP_CLEAR,       // VkLogicOp                                    logicOp
3015             0u,                      // uint32_t                                        attachmentCount
3016             DE_NULL,                 // const VkPipelineColorBlendAttachmentState*    pAttachments
3017             {0.0f, 0.0f, 0.0f, 0.0f} // float                                        blendConstants[4]
3018         };
3019 
3020         pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
3021             .setDefaultRasterizationState()
3022             .setDefaultDepthStencilState()
3023             .setDefaultMultisampleState()
3024             .setupVertexInputState(&inputState)
3025             .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule)
3026             .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
3027             .setupFragmentOutputState(*renderPass, 0u, &colorBlendState)
3028             .setMonolithicPipelineLayout(pipelineLayout)
3029             .buildPipeline();
3030     }
3031 
3032     // Offsets and sizes.
3033     const struct
3034     {
3035         size_t offset;
3036         size_t size;
3037     } pcPush[] = {
3038         // Push members doing some back-and-forth in the range.
3039         {offsetof(OverwritePushConstants, baseColor), sizeof(OverwritePushConstants::baseColor)},
3040         {offsetof(OverwritePushConstants, coords), sizeof(OverwritePushConstants::coords)},
3041         {offsetof(OverwritePushConstants, colorOffsets), sizeof(OverwritePushConstants::colorOffsets)},
3042         {offsetof(OverwritePushConstants, multiplier), sizeof(OverwritePushConstants::multiplier)},
3043         {offsetof(OverwritePushConstants, transparentGreen), sizeof(OverwritePushConstants::transparentGreen)},
3044     };
3045 
3046     beginCommandBuffer(vkd, cmdBuffer);
3047 
3048     // Transition layout for storage image.
3049     const auto preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
3050                                                         VK_IMAGE_LAYOUT_GENERAL, storageImage.get(), subresourceRange);
3051     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, writeStages, 0u, 0u, nullptr, 0u, nullptr, 1u,
3052                            &preImageBarrier);
3053 
3054     vkd.cmdBindDescriptorSets(cmdBuffer, m_params.bindPoint, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u,
3055                               nullptr);
3056 
3057     if (!isComp)
3058     {
3059         pipelineWrapper.bind(cmdBuffer);
3060         renderPass.begin(vkd, cmdBuffer, scissors[0]);
3061     }
3062     else
3063         vkd.cmdBindPipeline(cmdBuffer, m_params.bindPoint, pipeline.get());
3064 
3065     for (int pcIndex = 0; pcIndex < DE_LENGTH_OF_ARRAY(m_params.pushConstantValues); ++pcIndex)
3066     {
3067         const auto &pc = m_params.pushConstantValues[pcIndex];
3068 
3069         // Push all structure members separately.
3070         for (int pushIdx = 0; pushIdx < DE_LENGTH_OF_ARRAY(pcPush); ++pushIdx)
3071         {
3072             const auto &push    = pcPush[pushIdx];
3073             const void *dataPtr = reinterpret_cast<const void *>(reinterpret_cast<const char *>(&pc) + push.offset);
3074             vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), stageFlags, static_cast<uint32_t>(push.offset),
3075                                  static_cast<uint32_t>(push.size), dataPtr);
3076         }
3077 
3078         // Draw or dispatch.
3079         if (isComp)
3080             vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
3081         else
3082             vkd.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
3083     }
3084 
3085     if (!isComp)
3086         renderPass.end(vkd, cmdBuffer);
3087 
3088     // Copy storage image to output buffer.
3089     const auto postImageBarrier =
3090         makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL,
3091                                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, storageImage.get(), subresourceRange);
3092     vkd.cmdPipelineBarrier(cmdBuffer, writeStages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u,
3093                            &postImageBarrier);
3094 
3095     const auto copyRegion =
3096         makeBufferImageCopy(imageExtent, makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
3097     vkd.cmdCopyImageToBuffer(cmdBuffer, storageImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transferBuffer.get(),
3098                              1u, &copyRegion);
3099 
3100     const auto bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
3101                                                        transferBuffer.get(), 0ull, bufferSize);
3102     vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u,
3103                            &bufferBarrier, 0u, nullptr);
3104 
3105     endCommandBuffer(vkd, cmdBuffer);
3106     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
3107 
3108     // Verify output colors match.
3109     auto &bufferAlloc         = transferBuffer.getAllocation();
3110     const void *bufferHostPtr = bufferAlloc.getHostPtr();
3111     invalidateAlloc(vkd, device, bufferAlloc);
3112 
3113     const int iWidth  = static_cast<int>(imageExtent.width);
3114     const int iHeight = static_cast<int>(imageExtent.height);
3115     const int iDepth  = static_cast<int>(imageExtent.depth);
3116 
3117     tcu::ConstPixelBufferAccess outputAccess(tcuFormat, iWidth, iHeight, iDepth, bufferHostPtr);
3118 
3119     for (int pixelIdx = 0; pixelIdx < DE_LENGTH_OF_ARRAY(m_params.pushConstantValues); ++pixelIdx)
3120     {
3121         const auto &pc = m_params.pushConstantValues[pixelIdx];
3122         const tcu::UVec4 expectedValue =
3123             pc.baseColor * pc.multiplier +
3124             tcu::UVec4(pc.colorOffsets[0], pc.colorOffsets[1], pc.colorOffsets[2], pc.colorOffsets[3]) +
3125             pc.transparentGreen;
3126         const tcu::UVec4 outputValue = outputAccess.getPixelUint(pc.coords.x(), pc.coords.y());
3127 
3128         if (expectedValue != outputValue)
3129         {
3130             std::ostringstream msg;
3131             msg << "Unexpected value in output image at coords " << pc.coords << ": found " << outputValue
3132                 << " and expected " << expectedValue;
3133             TCU_FAIL(msg.str());
3134         }
3135     }
3136 
3137     return tcu::TestStatus::pass("Pass");
3138 }
3139 
addOverwriteCase(tcu::TestCaseGroup * group,tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,VkPipelineBindPoint bindPoint)3140 void addOverwriteCase(tcu::TestCaseGroup *group, tcu::TestContext &testCtx,
3141                       PipelineConstructionType pipelineConstructionType, VkPipelineBindPoint bindPoint)
3142 {
3143     const OverwritePushConstants pushConstants[4] = {
3144         //    coords                        baseColor                    multiplier                            colorOffsets                transparentGreen
3145         {tcu::IVec4(0, 0, 0, 0),
3146          tcu::UVec4(1u, 0u, 0u, 0u),
3147          tcu::UVec4(2u, 2u, 2u, 2u),
3148          {128u, 129u, 130u, 131u},
3149          tcu::UVec4(0u, 1u, 0u, 0u)},
3150         {tcu::IVec4(0, 1, 0, 0),
3151          tcu::UVec4(0u, 1u, 0u, 0u),
3152          tcu::UVec4(4u, 4u, 4u, 4u),
3153          {132u, 133u, 134u, 135u},
3154          tcu::UVec4(0u, 1u, 0u, 0u)},
3155         {tcu::IVec4(1, 0, 0, 0),
3156          tcu::UVec4(0u, 0u, 1u, 0u),
3157          tcu::UVec4(8u, 8u, 8u, 8u),
3158          {136u, 137u, 138u, 139u},
3159          tcu::UVec4(0u, 1u, 0u, 0u)},
3160         {tcu::IVec4(1, 1, 0, 0),
3161          tcu::UVec4(0u, 0u, 0u, 1u),
3162          tcu::UVec4(16u, 16u, 16u, 16u),
3163          {140u, 141u, 142u, 143u},
3164          tcu::UVec4(0u, 1u, 0u, 0u)},
3165     };
3166 
3167     OverwriteTestParams testParams;
3168 
3169     DE_ASSERT(DE_LENGTH_OF_ARRAY(pushConstants) == DE_LENGTH_OF_ARRAY(testParams.pushConstantValues));
3170     for (int pixelIdx = 0; pixelIdx < DE_LENGTH_OF_ARRAY(pushConstants); ++pixelIdx)
3171         testParams.pushConstantValues[pixelIdx] = pushConstants[pixelIdx];
3172 
3173     testParams.pipelineConstructionType = pipelineConstructionType;
3174     testParams.bindPoint                = bindPoint;
3175 
3176     // Test push constant range overwrites
3177     group->addChild(new OverwriteTestCase(testCtx, "overwrite", testParams));
3178 }
3179 
3180 } // namespace
3181 
createPushConstantTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)3182 tcu::TestCaseGroup *createPushConstantTests(tcu::TestContext &testCtx,
3183                                             PipelineConstructionType pipelineConstructionType)
3184 {
3185     static const struct
3186     {
3187         const char *name;
3188         uint32_t count;
3189         PushConstantData range[MAX_RANGE_COUNT];
3190         bool hasMultipleUpdates;
3191         IndexType indexType;
3192     } graphicsParams[] = {
3193         // test range size is 4 bytes(minimum valid size)
3194         {"range_size_4", 1u, {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, {0, 4}}}, false, INDEX_TYPE_CONST_LITERAL},
3195         // test range size is 16 bytes, and together with a normal uniform
3196         {"range_size_16", 1u, {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}}}, false, INDEX_TYPE_CONST_LITERAL},
3197         // test range size is 128 bytes(maximum valid size)
3198         {"range_size_128", 1u, {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 128}, {0, 128}}}, false, INDEX_TYPE_CONST_LITERAL},
3199         // test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
3200         {"count_2_shaders_vert_frag",
3201          2u,
3202          {
3203              {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3204              {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3205          },
3206          false,
3207          INDEX_TYPE_CONST_LITERAL},
3208         // test range count is 3, use vertex, geometry and fragment shaders
3209         {"count_3_shaders_vert_geom_frag",
3210          3u,
3211          {
3212              {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3213              {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3214              {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3215          },
3216          false,
3217          INDEX_TYPE_CONST_LITERAL},
3218         // test range count is 5, use vertex, tessellation, geometry and fragment shaders
3219         {"count_5_shaders_vert_tess_geom_frag",
3220          5u,
3221          {
3222              {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3223              {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3224              {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3225              {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4}, {24, 4}},
3226              {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16}, {32, 16}},
3227          },
3228          false,
3229          INDEX_TYPE_CONST_LITERAL},
3230         // test range count is 1, vertex and fragment shaders share one range
3231         {"count_1_shader_vert_frag",
3232          1u,
3233          {{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4}, {0, 4}}},
3234          false,
3235          INDEX_TYPE_CONST_LITERAL},
3236         // test data partial update and multiple times update
3237         {"data_update_partial_1",
3238          1u,
3239          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {4, 24}}},
3240          false,
3241          INDEX_TYPE_CONST_LITERAL},
3242         // test partial update of the values
3243         {"data_update_partial_2",
3244          1u,
3245          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 48}, {32, 16}}},
3246          false,
3247          INDEX_TYPE_CONST_LITERAL},
3248         // test multiple times update of the values
3249         {"data_update_multiple", 1u, {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, {0, 4}}}, true, INDEX_TYPE_CONST_LITERAL},
3250         // dynamically uniform indexing of vertex, matrix, and array in vertex shader
3251         {"dynamic_index_vert",
3252          1u,
3253          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 64}, {0, 64}}},
3254          false,
3255          INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR},
3256         // dynamically uniform indexing of vertex, matrix, and array in fragment shader
3257         {"dynamic_index_frag",
3258          1u,
3259          {{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 64}, {0, 64}}},
3260          false,
3261          INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR}};
3262 
3263     static const struct
3264     {
3265         const char *name;
3266         uint32_t count;
3267         PushConstantData range[MAX_RANGE_COUNT];
3268     } overlapGraphicsParams[] = {
3269         // overlapping range count is 2, use vertex and fragment shaders
3270         {"overlap_2_shaders_vert_frag",
3271          2u,
3272          {
3273              {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3274              {{VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36}, {12, 36}},
3275          }},
3276         // overlapping range count is 3, use vertex, geometry and fragment shaders
3277         {"overlap_3_shaders_vert_geom_frag",
3278          3u,
3279          {{{VK_SHADER_STAGE_VERTEX_BIT, 12, 36}, {12, 36}},
3280           {{VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32}, {16, 16}},
3281           {{VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4}, {20, 4}}}},
3282         // overlapping range count is 4, use vertex, tessellation and fragment shaders
3283         {"overlap_4_shaders_vert_tess_frag",
3284          4u,
3285          {{{VK_SHADER_STAGE_VERTEX_BIT, 8, 4}, {8, 4}},
3286           {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 128}, {52, 76}},
3287           {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 56, 8}, {56, 8}},
3288           {{VK_SHADER_STAGE_FRAGMENT_BIT, 60, 36}, {60, 36}}}},
3289         // overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders
3290         {"overlap_5_shaders_vert_tess_geom_frag",
3291          5u,
3292          {{{VK_SHADER_STAGE_VERTEX_BIT, 40, 8}, {40, 8}},
3293           {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12}, {32, 12}},
3294           {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16}, {48, 16}},
3295           {{VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36}, {28, 36}},
3296           {{VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8}, {60, 4}}}}};
3297 
3298     static const struct
3299     {
3300         const char *name;
3301         ComputeTestType type;
3302         PushConstantData range;
3303     } computeParams[] = {
3304         // test compute pipeline
3305         {
3306             "simple_test",
3307             CTT_SIMPLE,
3308             {{VK_SHADER_STAGE_COMPUTE_BIT, 0, 16}, {0, 16}},
3309         },
3310         // test push constant that is dynamically unused
3311         {
3312             "uninitialized",
3313             CTT_UNINITIALIZED,
3314             {{VK_SHADER_STAGE_COMPUTE_BIT, 0, 16}, {0, 16}},
3315         },
3316     };
3317 
3318     static const struct
3319     {
3320         const char *name;
3321         PushConstantData range[MAX_RANGE_COUNT];
3322         std::vector<CommandData> cmdList;
3323     } lifetimeParams[] = {
3324         // bind different layout with the same range
3325         {"push_range0_bind_layout1",
3326          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}},
3327          {
3328              {CMD_PUSH_CONSTANT, 0},
3329              {CMD_BIND_PIPELINE_GRAPHICS, 1},
3330              {CMD_DRAW, -1},
3331          }},
3332         // bind layout with same range then push different range
3333         {"push_range1_bind_layout1_push_range0",
3334          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}},
3335          {
3336              {CMD_PUSH_CONSTANT, 1},
3337              {CMD_BIND_PIPELINE_GRAPHICS, 1},
3338              {CMD_DRAW, -1},
3339              {CMD_PUSH_CONSTANT, 0},
3340              {CMD_DRAW, -1},
3341          }},
3342         // same range same layout then same range from a different layout and same range from the same layout
3343         {"push_range0_bind_layout0_push_range1_push_range0",
3344          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}},
3345          {
3346              {CMD_PUSH_CONSTANT, 0},
3347              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3348              {CMD_PUSH_CONSTANT, 1},
3349              {CMD_PUSH_CONSTANT, 0},
3350              {CMD_DRAW, -1},
3351          }},
3352         // same range same layout then diff range and same range update
3353         {"push_range0_bind_layout0_push_diff_overlapping_range1_push_range0",
3354          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}},
3355          {
3356              {CMD_PUSH_CONSTANT, 0},
3357              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3358              {CMD_PUSH_CONSTANT, 1},
3359              {CMD_PUSH_CONSTANT, 0},
3360              {CMD_DRAW, -1},
3361          }},
3362         // update push constant bind different layout with the same range then bind correct layout
3363         {"push_range0_bind_layout1_bind_layout0",
3364          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}},
3365          {
3366              {CMD_PUSH_CONSTANT, 0},
3367              {CMD_BIND_PIPELINE_GRAPHICS, 1},
3368              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3369              {CMD_DRAW, -1},
3370          }},
3371         // update push constant then bind different layout with overlapping range then bind correct layout
3372         {"push_range0_bind_layout1_overlapping_range_bind_layout0",
3373          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}},
3374          {
3375              {CMD_PUSH_CONSTANT, 0},
3376              {CMD_BIND_PIPELINE_GRAPHICS, 1},
3377              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3378              {CMD_DRAW, -1},
3379          }},
3380         // bind different layout with different range then update push constant and bind correct layout
3381         {"bind_layout1_push_range0_bind_layout0",
3382          {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 32}, {0, 32}}, {{VK_SHADER_STAGE_VERTEX_BIT, 16, 32}, {16, 32}}},
3383          {
3384              {CMD_BIND_PIPELINE_GRAPHICS, 1},
3385              {CMD_PUSH_CONSTANT, 0},
3386              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3387              {CMD_DRAW, -1},
3388          }},
3389         // change pipeline same range, bind then push, stages vertex and compute
3390         {"pipeline_change_same_range_bind_push_vert_and_comp",
3391          {{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}},
3392           {{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}}},
3393          {
3394              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3395              {CMD_BIND_PIPELINE_COMPUTE, 1},
3396              {CMD_PUSH_CONSTANT, 0},
3397              {CMD_DRAW, -1},
3398              {CMD_PUSH_CONSTANT, 1},
3399              {CMD_DISPATCH, -1},
3400          }},
3401         // change pipeline different range overlapping, bind then push, stages vertex and compute
3402         {"pipeline_change_diff_range_bind_push_vert_and_comp",
3403          {{{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 0, 32}, {0, 32}},
3404           {{VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_COMPUTE_BIT, 16, 32}, {16, 32}}},
3405          {
3406              {CMD_BIND_PIPELINE_GRAPHICS, 0},
3407              {CMD_BIND_PIPELINE_COMPUTE, 1},
3408              {CMD_PUSH_CONSTANT, 0},
3409              {CMD_DRAW, -1},
3410              {CMD_PUSH_CONSTANT, 1},
3411              {CMD_DISPATCH, -1},
3412          }}};
3413 
3414     de::MovePtr<tcu::TestCaseGroup> pushConstantTests(new tcu::TestCaseGroup(testCtx, "push_constant"));
3415 
3416     de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "graphics_pipeline"));
3417     for (int cmd = 0; cmd < 2; ++cmd)
3418     {
3419         bool pushConstant2 = cmd != 0;
3420 #ifdef CTS_USES_VULKANSC
3421         if (pushConstant2)
3422             continue;
3423 #endif
3424         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
3425         {
3426             std::string name = graphicsParams[ndx].name;
3427             if (pushConstant2)
3428                 name += "_command2";
3429             graphicsTests->addChild(new PushConstantGraphicsDisjointTest(
3430                 testCtx, name.c_str(), pipelineConstructionType, graphicsParams[ndx].count, graphicsParams[ndx].range,
3431                 graphicsParams[ndx].hasMultipleUpdates, graphicsParams[ndx].indexType, pushConstant2));
3432         }
3433 
3434         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(overlapGraphicsParams); ndx++)
3435         {
3436             std::string name = overlapGraphicsParams[ndx].name;
3437             if (pushConstant2)
3438                 name += "_command2";
3439             graphicsTests->addChild(new PushConstantGraphicsOverlapTest(
3440                 testCtx, name.c_str(), pipelineConstructionType, overlapGraphicsParams[ndx].count,
3441                 overlapGraphicsParams[ndx].range, pushConstant2));
3442         }
3443     }
3444     addOverwriteCase(graphicsTests.get(), testCtx, pipelineConstructionType, VK_PIPELINE_BIND_POINT_GRAPHICS);
3445 
3446     // tests for unused push constants:
3447     // push constants that are specified in pipeline layout but not used in shaders
3448     {
3449         {
3450             static const struct
3451             {
3452                 const char *name;
3453                 uint32_t count;
3454                 PushConstantData range[MAX_RANGE_COUNT];
3455                 bool hasMultipleUpdates;
3456                 IndexType indexType;
3457                 PushConstantUseStage pcUsedStages;
3458             } unusedDisjointPCTestParams[] = {
3459                 // test range size is 4 bytes(minimum valid size)
3460                 // no shader stage using push constants
3461                 {"unused_disjoint_1",
3462                  1u,
3463                  {{{VK_SHADER_STAGE_VERTEX_BIT, 0, 4}, {0, 4}}},
3464                  false,
3465                  INDEX_TYPE_CONST_LITERAL,
3466                  PC_USE_STAGE_NONE
3467 
3468                 },
3469                 // test range count, including all valid shader stage in graphics pipeline
3470                 // vertex shader using push constants, fragment shader not using push constants
3471                 {"unused_disjoint_2",
3472                  2u,
3473                  {
3474                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3475                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3476                  },
3477                  false,
3478                  INDEX_TYPE_CONST_LITERAL,
3479                  PC_USE_STAGE_VERTEX},
3480                 // test range count is 3, use vertex, geometry and fragment shaders
3481                 // no shader stage using push constants
3482                 {"unused_disjoint_3",
3483                  3u,
3484                  {
3485                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3486                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3487                      {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3488                  },
3489                  false,
3490                  INDEX_TYPE_CONST_LITERAL,
3491                  PC_USE_STAGE_NONE},
3492                 // test range count is 3, use vertex, geometry and fragment shaders
3493                 // geometry shader using push constants, vertex and fragment shader not using push constants
3494                 {"unused_disjoint_4",
3495                  3u,
3496                  {
3497                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3498                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3499                      {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3500                  },
3501                  false,
3502                  INDEX_TYPE_CONST_LITERAL,
3503                  PC_USE_STAGE_GEOM},
3504                 // test range count is 5, use vertex, tessellation, geometry and fragment shaders
3505                 // no shader stage using push constants
3506                 {"unused_disjoint_5",
3507                  5u,
3508                  {
3509                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3510                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3511                      {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3512                      {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4}, {24, 4}},
3513                      {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16}, {32, 16}},
3514                  },
3515                  false,
3516                  INDEX_TYPE_CONST_LITERAL,
3517                  PC_USE_STAGE_NONE},
3518                 // test range count is 5, use vertex, tessellation, geometry and fragment shaders
3519                 // tess shader stages using push constants, vertex, geometry and fragment shader not using push constants
3520                 {"unused_disjoint_6",
3521                  5u,
3522                  {
3523                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3524                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4}, {16, 4}},
3525                      {{VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4}, {20, 4}},
3526                      {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4}, {24, 4}},
3527                      {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16}, {32, 16}},
3528                  },
3529                  false,
3530                  INDEX_TYPE_CONST_LITERAL,
3531                  PC_USE_STAGE_TESC | PC_USE_STAGE_TESE}};
3532 
3533             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(unusedDisjointPCTestParams); ndx++)
3534             {
3535                 graphicsTests->addChild(new PushConstantGraphicsDisjointTest(
3536                     testCtx, unusedDisjointPCTestParams[ndx].name, pipelineConstructionType,
3537                     unusedDisjointPCTestParams[ndx].count, unusedDisjointPCTestParams[ndx].range,
3538                     unusedDisjointPCTestParams[ndx].hasMultipleUpdates, unusedDisjointPCTestParams[ndx].indexType,
3539                     unusedDisjointPCTestParams[ndx].pcUsedStages));
3540             }
3541         }
3542         {
3543             static const struct
3544             {
3545                 const char *name;
3546                 uint32_t count;
3547                 PushConstantData range[MAX_RANGE_COUNT];
3548                 PushConstantUseStage pcUsedStages;
3549 
3550             } unusedOverlapPCTestParams[] = {
3551                 // overlapping range count is 2, use vertex and fragment shaders
3552                 // no shader stage using push constants
3553                 {"unused_overlap_1",
3554                  2u,
3555                  {
3556                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3557                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36}, {12, 36}},
3558                  },
3559                  PC_USE_STAGE_NONE},
3560                 // overlapping range count is 2, use vertex and fragment shaders
3561                 // vertex shader using push constants, fragment shader not using push constants
3562                 {"unused_overlap_2",
3563                  2u,
3564                  {
3565                      {{VK_SHADER_STAGE_VERTEX_BIT, 0, 16}, {0, 16}},
3566                      {{VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36}, {12, 36}},
3567                  },
3568                  PC_USE_STAGE_VERTEX},
3569                 // overlapping range count is 3, use vertex, geometry and fragment shaders
3570                 // no shader stage using push constants
3571                 {"unused_overlap_3",
3572                  3u,
3573                  {{{VK_SHADER_STAGE_VERTEX_BIT, 12, 36}, {12, 36}},
3574                   {{VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32}, {16, 16}},
3575                   {{VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4}, {20, 4}}},
3576                  PC_USE_STAGE_NONE},
3577                 // overlapping range count is 3, use vertex, geometry and fragment shaders
3578                 // geometry shader using push constants, vertex and fragment shader not using push constants
3579                 {"unused_overlap_4",
3580                  3u,
3581                  {{{VK_SHADER_STAGE_VERTEX_BIT, 12, 36}, {12, 36}},
3582                   {{VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32}, {16, 16}},
3583                   {{VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4}, {20, 4}}},
3584                  PC_USE_STAGE_GEOM},
3585                 // overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders
3586                 // no shader stage using push constants
3587                 {"unused_overlap_5",
3588                  5u,
3589                  {{{VK_SHADER_STAGE_VERTEX_BIT, 40, 8}, {40, 8}},
3590                   {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12}, {32, 12}},
3591                   {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16}, {48, 16}},
3592                   {{VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36}, {28, 36}},
3593                   {{VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8}, {60, 4}}},
3594                  PC_USE_STAGE_NONE},
3595                 // overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders
3596                 // tess shader stages using push constants, vertex, geometry and fragment shader not using push constants
3597                 {"unused_overlap_6",
3598                  5u,
3599                  {{{VK_SHADER_STAGE_VERTEX_BIT, 40, 8}, {40, 8}},
3600                   {{VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12}, {32, 12}},
3601                   {{VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16}, {48, 16}},
3602                   {{VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36}, {28, 36}},
3603                   {{VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8}, {60, 4}}},
3604                  PC_USE_STAGE_TESC | PC_USE_STAGE_TESE}};
3605 
3606             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(unusedOverlapPCTestParams); ndx++)
3607             {
3608                 graphicsTests->addChild(new PushConstantGraphicsOverlapTest(
3609                     testCtx, unusedOverlapPCTestParams[ndx].name, pipelineConstructionType,
3610                     unusedOverlapPCTestParams[ndx].count, unusedOverlapPCTestParams[ndx].range,
3611                     unusedOverlapPCTestParams[ndx].pcUsedStages));
3612             }
3613         }
3614     }
3615 
3616     pushConstantTests->addChild(graphicsTests.release());
3617 
3618     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3619     {
3620         de::MovePtr<tcu::TestCaseGroup> computeTests(new tcu::TestCaseGroup(testCtx, "compute_pipeline"));
3621         for (const auto &params : computeParams)
3622         {
3623             computeTests->addChild(new PushConstantComputeTest(testCtx, params.name, params.type, params.range));
3624         }
3625         addOverwriteCase(computeTests.get(), testCtx, pipelineConstructionType, VK_PIPELINE_BIND_POINT_COMPUTE);
3626         pushConstantTests->addChild(computeTests.release());
3627     }
3628 
3629     de::MovePtr<tcu::TestCaseGroup> lifetimeTests(new tcu::TestCaseGroup(testCtx, "lifetime"));
3630     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(lifetimeParams); ndx++)
3631     {
3632         lifetimeTests->addChild(new PushConstantLifetimeTest(testCtx, lifetimeParams[ndx].name,
3633                                                              pipelineConstructionType, lifetimeParams[ndx].range,
3634                                                              lifetimeParams[ndx].cmdList));
3635     }
3636     pushConstantTests->addChild(lifetimeTests.release());
3637 
3638     return pushConstantTests.release();
3639 }
3640 
3641 } // namespace pipeline
3642 } // namespace vkt
3643