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