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