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