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