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