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 ¶ms);
~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 ¶ms);
~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 ¶ms)
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 ¶ms)
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, ©Region);
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 ¶ms : 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