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