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 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "deMemory.h"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "tcuTestLog.hpp"
47
48 #include <algorithm>
49 #include <sstream>
50 #include <vector>
51
52 namespace vkt
53 {
54 namespace pipeline
55 {
56
57 using namespace vk;
58
59 namespace
60 {
61
62 enum
63 {
64 TRIANGLE_COUNT = 2,
65 MAX_RANGE_COUNT = 5
66 };
67
68 enum RangeSizeCase
69 {
70 SIZE_CASE_4 = 0,
71 SIZE_CASE_8,
72 SIZE_CASE_12,
73 SIZE_CASE_16,
74 SIZE_CASE_32,
75 SIZE_CASE_36,
76 SIZE_CASE_48,
77 SIZE_CASE_128,
78 SIZE_CASE_UNSUPPORTED
79 };
80
81 struct PushConstantData
82 {
83 struct PushConstantRange
84 {
85 VkShaderStageFlags shaderStage;
86 deUint32 offset;
87 deUint32 size;
88 } range;
89 struct PushConstantUpdate
90 {
91 deUint32 offset;
92 deUint32 size;
93 } update;
94 };
95
96 // These values will be loaded from push constants and used as an index
97 static const deUint32 DYNAMIC_VEC_INDEX = 2u;
98 static const deUint32 DYNAMIC_MAT_INDEX = 0u;
99 static const deUint32 DYNAMIC_ARR_INDEX = 3u;
100
101 // These reference values will be compared in the shader to ensure the correct index was read
102 static const float DYNAMIC_VEC_CONSTANT = 0.25f;
103 static const float DYNAMIC_MAT_CONSTANT = 0.50f;
104 static const float DYNAMIC_ARR_CONSTANT = 0.75f;
105
106 enum IndexType
107 {
108 INDEX_TYPE_CONST_LITERAL = 0,
109 INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR,
110
111 INDEX_TYPE_LAST
112 };
113
getShaderStageNameStr(VkShaderStageFlags stageFlags)114 std::string getShaderStageNameStr (VkShaderStageFlags stageFlags)
115 {
116 const VkShaderStageFlags shaderStages[] =
117 {
118 VK_SHADER_STAGE_VERTEX_BIT,
119 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
120 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
121 VK_SHADER_STAGE_GEOMETRY_BIT,
122 VK_SHADER_STAGE_FRAGMENT_BIT
123 };
124
125 const char* shaderStageNames[] =
126 {
127 "VK_SHADER_STAGE_VERTEX_BIT",
128 "VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT",
129 "VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT",
130 "VK_SHADER_STAGE_GEOMETRY_BIT",
131 "VK_SHADER_STAGE_FRAGMENT_BIT",
132 };
133
134 std::stringstream shaderStageStr;
135
136 for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
137 {
138 if (stageFlags & shaderStages[stageNdx])
139 {
140 if (!(shaderStageStr.str().empty()))
141 shaderStageStr << " | ";
142
143 shaderStageStr << shaderStageNames[stageNdx];
144 }
145 }
146
147 return shaderStageStr.str();
148 }
149
150 class PushConstantGraphicsTestInstance : public vkt::TestInstance
151 {
152 public:
153 PushConstantGraphicsTestInstance (Context& context,
154 const deUint32 rangeCount,
155 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
156 const deBool multipleUpdate,
157 const IndexType indexType);
158 virtual ~PushConstantGraphicsTestInstance (void);
159 void init (void);
160 virtual tcu::TestStatus iterate (void);
161 virtual std::vector<VkPushConstantRange> getPushConstantRanges (void) = 0;
162 virtual void updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout) = 0;
163 virtual void setReferenceColor (tcu::Vec4 initColor) = 0;
164 void createShaderModule (const DeviceInterface& vk,
165 VkDevice device,
166 const BinaryCollection& programCollection,
167 const char* name,
168 Move<VkShaderModule>* module);
169 std::vector<Vertex4RGBA> createQuad (const float size);
170 tcu::TestStatus verifyImage (void);
171
172 protected:
173 std::vector<Vertex4RGBA> m_vertices;
174 const deUint32 m_rangeCount;
175 PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
176 const IndexType m_indexType;
177
178 private:
179 const tcu::UVec2 m_renderSize;
180 const VkFormat m_colorFormat;
181 const deBool m_multipleUpdate;
182
183 VkImageCreateInfo m_colorImageCreateInfo;
184 Move<VkImage> m_colorImage;
185 de::MovePtr<Allocation> m_colorImageAlloc;
186 Move<VkImageView> m_colorAttachmentView;
187 Move<VkRenderPass> m_renderPass;
188 Move<VkFramebuffer> m_framebuffer;
189
190 Move<VkShaderModule> m_vertexShaderModule;
191 Move<VkShaderModule> m_fragmentShaderModule;
192 Move<VkShaderModule> m_geometryShaderModule;
193 Move<VkShaderModule> m_tessControlShaderModule;
194 Move<VkShaderModule> m_tessEvaluationShaderModule;
195
196 VkShaderStageFlags m_shaderFlags;
197 std::vector<VkPipelineShaderStageCreateInfo> m_shaderStage;
198
199 Move<VkBuffer> m_vertexBuffer;
200 de::MovePtr<Allocation> m_vertexBufferAlloc;
201
202 Move<VkBuffer> m_uniformBuffer;
203 de::MovePtr<Allocation> m_uniformBufferAlloc;
204 Move<VkDescriptorPool> m_descriptorPool;
205 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
206 Move<VkDescriptorSet> m_descriptorSet;
207
208 Move<VkPipelineLayout> m_pipelineLayout;
209 Move<VkPipeline> m_graphicsPipelines;
210
211 Move<VkCommandPool> m_cmdPool;
212 Move<VkCommandBuffer> m_cmdBuffer;
213 };
214
createShaderModule(const DeviceInterface & vk,VkDevice device,const BinaryCollection & programCollection,const char * name,Move<VkShaderModule> * module)215 void PushConstantGraphicsTestInstance::createShaderModule (const DeviceInterface& vk,
216 VkDevice device,
217 const BinaryCollection& programCollection,
218 const char* name,
219 Move<VkShaderModule>* module)
220 {
221 *module = vk::createShaderModule(vk, device, programCollection.get(name), 0);
222 }
223
createQuad(const float size)224 std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
225 {
226 std::vector<Vertex4RGBA> vertices;
227
228 const tcu::Vec4 color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
229 const Vertex4RGBA lowerLeftVertex = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
230 const Vertex4RGBA lowerRightVertex = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
231 const Vertex4RGBA UpperLeftVertex = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
232 const Vertex4RGBA UpperRightVertex = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
233
234 vertices.push_back(lowerLeftVertex);
235 vertices.push_back(lowerRightVertex);
236 vertices.push_back(UpperLeftVertex);
237 vertices.push_back(UpperLeftVertex);
238 vertices.push_back(lowerRightVertex);
239 vertices.push_back(UpperRightVertex);
240
241 return vertices;
242 }
243
PushConstantGraphicsTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)244 PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context& context,
245 const deUint32 rangeCount,
246 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
247 deBool multipleUpdate,
248 IndexType indexType)
249 : vkt::TestInstance (context)
250 , m_rangeCount (rangeCount)
251 , m_indexType (indexType)
252 , m_renderSize (32, 32)
253 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
254 , m_multipleUpdate (multipleUpdate)
255 , m_shaderFlags (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
256 {
257 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
258 }
259
init(void)260 void PushConstantGraphicsTestInstance::init (void)
261 {
262 const DeviceInterface& vk = m_context.getDeviceInterface();
263 const VkDevice vkDevice = m_context.getDevice();
264 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
265 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
266 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
267 const std::vector<VkPushConstantRange> pushConstantRanges = getPushConstantRanges();
268 bool useTessellation = false;
269 bool useGeometry = false;
270
271 // Create color image
272 {
273 const VkImageCreateInfo colorImageParams =
274 {
275 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
276 DE_NULL, // const void* pNext;
277 0u, // VkImageCreateFlags flags;
278 VK_IMAGE_TYPE_2D, // VkImageType imageType;
279 m_colorFormat, // VkFormat format;
280 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
281 1u, // deUint32 mipLevels;
282 1u, // deUint32 arrayLayers;
283 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
284 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
285 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
286 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
287 1u, // deUint32 queueFamilyIndexCount;
288 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
289 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
290 };
291
292 m_colorImageCreateInfo = colorImageParams;
293 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
294
295 // Allocate and bind color image memory
296 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
297 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
298 }
299
300 // Create color attachment view
301 {
302 const VkImageViewCreateInfo colorAttachmentViewParams =
303 {
304 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
305 DE_NULL, // const void* pNext;
306 0u, // VkImageViewCreateFlags flags;
307 *m_colorImage, // VkImage image;
308 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
309 m_colorFormat, // VkFormat format;
310 componentMappingRGBA, // VkChannelMapping channels;
311 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
312 };
313
314 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
315 }
316
317 // Create render pass
318 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
319
320 // Create framebuffer
321 {
322 const VkImageView attachmentBindInfos[1] =
323 {
324 *m_colorAttachmentView
325 };
326
327 const VkFramebufferCreateInfo framebufferParams =
328 {
329 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
330 DE_NULL, // const void* pNext;
331 0u, // VkFramebufferCreateFlags flags;
332 *m_renderPass, // VkRenderPass renderPass;
333 1u, // deUint32 attachmentCount;
334 attachmentBindInfos, // const VkImageView* pAttachments;
335 (deUint32)m_renderSize.x(), // deUint32 width;
336 (deUint32)m_renderSize.y(), // deUint32 height;
337 1u // deUint32 layers;
338 };
339
340 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
341 }
342
343 // Create pipeline layout
344 {
345 // create descriptor set layout
346 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
347
348 // create descriptor pool
349 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
350
351 // create uniform buffer
352 const VkBufferCreateInfo uniformBufferCreateInfo =
353 {
354 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
355 DE_NULL, // const void* pNext;
356 0u, // VkBufferCreateFlags flags
357 16u, // VkDeviceSize size;
358 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, // VkBufferUsageFlags usage;
359 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
360 1u, // deUint32 queueFamilyCount;
361 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
362 };
363
364 m_uniformBuffer = createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
365 m_uniformBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
366 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
367
368 const tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
369 deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
370 flushAlloc(vk, vkDevice, *m_uniformBufferAlloc);
371
372 // create and update descriptor set
373 const VkDescriptorSetAllocateInfo allocInfo =
374 {
375 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
376 DE_NULL, // const void* pNext;
377 *m_descriptorPool, // VkDescriptorPool descriptorPool;
378 1u, // deUint32 setLayoutCount;
379 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
380 };
381 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
382
383 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
384
385 DescriptorSetUpdateBuilder()
386 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
387 .update(vk, vkDevice);
388
389 // create pipeline layout
390 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
391 {
392 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
393 DE_NULL, // const void* pNext;
394 0u, // VkPipelineLayoutCreateFlags flags;
395 1u, // deUint32 descriptorSetCount;
396 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
397 (deUint32)pushConstantRanges.size(), // deUint32 pushConstantRangeCount;
398 &pushConstantRanges.front() // const VkPushConstantRange* pPushConstantRanges;
399 };
400
401 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
402 }
403
404 // Create shaders
405 {
406 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
407 {
408 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
409 {
410 m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
411 }
412 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
413 {
414 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
415 }
416 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
417 {
418 m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
419 }
420 }
421
422 VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
423
424 createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", &m_vertexShaderModule);
425 if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
426 {
427 if (features.tessellationShader == VK_FALSE)
428 {
429 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
430 }
431 createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", &m_tessControlShaderModule);
432 createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", &m_tessEvaluationShaderModule);
433 useTessellation = true;
434 }
435 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
436 {
437 if (features.geometryShader == VK_FALSE)
438 {
439 TCU_THROW(NotSupportedError, "Geometry Not Supported");
440 }
441 createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", &m_geometryShaderModule);
442 useGeometry = true;
443 }
444 createShaderModule(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", &m_fragmentShaderModule);
445 }
446
447 // Create pipeline
448 {
449 const VkVertexInputBindingDescription vertexInputBindingDescription =
450 {
451 0u, // deUint32 binding;
452 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
453 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
454 };
455
456 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
457 {
458 {
459 0u, // deUint32 location;
460 0u, // deUint32 binding;
461 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
462 0u // deUint32 offsetInBytes;
463 },
464 {
465 1u, // deUint32 location;
466 0u, // deUint32 binding;
467 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
468 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
469 }
470 };
471
472 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
473 {
474 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
475 DE_NULL, // const void* pNext;
476 0u, // vkPipelineVertexInputStateCreateFlags flags;
477 1u, // deUint32 bindingCount;
478 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
479 2u, // deUint32 attributeCount;
480 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
481 };
482
483 const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
484
485 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
486 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
487
488 m_graphicsPipelines = makeGraphicsPipeline(vk, // const DeviceInterface& vk
489 vkDevice, // const VkDevice device
490 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
491 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
492 useTessellation ? *m_tessControlShaderModule : DE_NULL, // const VkShaderModule tessellationControlShaderModule
493 useTessellation ? *m_tessEvaluationShaderModule : DE_NULL, // const VkShaderModule tessellationEvalShaderModule
494 useGeometry ? *m_geometryShaderModule : DE_NULL, // const VkShaderModule geometryShaderModule
495 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
496 *m_renderPass, // const VkRenderPass renderPass
497 viewports, // const std::vector<VkViewport>& viewports
498 scissors, // const std::vector<VkRect2D>& scissors
499 topology, // const VkPrimitiveTopology topology
500 0u, // const deUint32 subpass
501 3u, // const deUint32 patchControlPoints
502 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
503 }
504
505 // Create vertex buffer
506 {
507 m_vertices = createQuad(1.0f);
508
509 const VkBufferCreateInfo vertexBufferParams =
510 {
511 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
512 DE_NULL, // const void* pNext;
513 0u, // VkBufferCreateFlags flags;
514 (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()), // VkDeviceSize size;
515 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
516 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
517 1u, // deUint32 queueFamilyCount;
518 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
519 };
520
521 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
522 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
523
524 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
525
526 // Load vertices into vertex buffer
527 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
528 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
529 }
530
531 // Create command pool
532 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
533
534 // Create command buffer
535 {
536 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
537
538 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
539
540 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
541
542 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
543
544 // Update push constant values
545 updatePushConstants(*m_cmdBuffer, *m_pipelineLayout);
546
547 // draw quad
548 const VkDeviceSize triangleOffset = (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
549
550 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
551 {
552 VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
553
554 if (m_multipleUpdate)
555 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
556
557 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
558 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
559 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
560
561 vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
562 }
563
564 endRenderPass(vk, *m_cmdBuffer);
565 endCommandBuffer(vk, *m_cmdBuffer);
566 }
567 }
568
~PushConstantGraphicsTestInstance(void)569 PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
570 {
571 }
572
iterate(void)573 tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
574 {
575 init();
576
577 const DeviceInterface& vk = m_context.getDeviceInterface();
578 const VkDevice vkDevice = m_context.getDevice();
579 const VkQueue queue = m_context.getUniversalQueue();
580
581 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
582
583 return verifyImage();
584 }
585
verifyImage(void)586 tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
587 {
588 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
589 const tcu::TextureFormat tcuDepthFormat = tcu::TextureFormat();
590 const ColorVertexShader vertexShader;
591 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuDepthFormat);
592 const rr::Program program (&vertexShader, &fragmentShader);
593 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
594 bool compareOk = false;
595
596 // Render reference image
597 {
598 if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
599 {
600 m_vertices = createQuad(0.5f);
601 }
602
603 setReferenceColor(m_vertices[0].color);
604
605 if (m_multipleUpdate)
606 {
607 for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
608 {
609 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
610 }
611 for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
612 {
613 m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
614 }
615 }
616
617 for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
618 {
619 rr::RenderState renderState(refRenderer.getViewportState());
620
621 refRenderer.draw(renderState,
622 rr::PRIMITIVETYPE_TRIANGLES,
623 std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
624 m_vertices.begin() + (triangleNdx + 1) * 3));
625 }
626 }
627
628 // Compare result with reference image
629 {
630 const DeviceInterface& vk = m_context.getDeviceInterface();
631 const VkDevice vkDevice = m_context.getDevice();
632 const VkQueue queue = m_context.getUniversalQueue();
633 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
634 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
635 de::MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
636
637 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
638 "IntImageCompare",
639 "Image comparison",
640 refRenderer.getAccess(),
641 result->getAccess(),
642 tcu::UVec4(2, 2, 2, 2),
643 tcu::IVec3(1, 1, 0),
644 true,
645 tcu::COMPARE_LOG_RESULT);
646 }
647
648 if (compareOk)
649 return tcu::TestStatus::pass("Result image matches reference");
650 else
651 return tcu::TestStatus::fail("Image mismatch");
652 }
653
654 class PushConstantGraphicsDisjointInstance : public PushConstantGraphicsTestInstance
655 {
656 public:
657 PushConstantGraphicsDisjointInstance (Context& context,
658 const deUint32 rangeCount,
659 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
660 const deBool multipleUpdate,
661 const IndexType indexType);
662 virtual ~PushConstantGraphicsDisjointInstance (void);
663 std::vector<VkPushConstantRange> getPushConstantRanges (void);
664 void updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
665 void setReferenceColor (tcu::Vec4 initColor);
666 };
667
668
PushConstantGraphicsDisjointInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)669 PushConstantGraphicsDisjointInstance::PushConstantGraphicsDisjointInstance (Context& context,
670 const deUint32 rangeCount,
671 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
672 deBool multipleUpdate,
673 IndexType indexType)
674 : PushConstantGraphicsTestInstance (context, rangeCount, pushConstantRange, multipleUpdate, indexType)
675 {
676 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
677 }
678
~PushConstantGraphicsDisjointInstance(void)679 PushConstantGraphicsDisjointInstance::~PushConstantGraphicsDisjointInstance(void)
680 {
681 }
682
getPushConstantRanges(void)683 std::vector<VkPushConstantRange> PushConstantGraphicsDisjointInstance::getPushConstantRanges (void)
684 {
685 std::vector<VkPushConstantRange> pushConstantRanges;
686
687 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
688 {
689 const VkPushConstantRange pushConstantRange =
690 {
691 m_pushConstantRange[rangeNdx].range.shaderStage,
692 m_pushConstantRange[rangeNdx].range.offset,
693 m_pushConstantRange[rangeNdx].range.size
694 };
695
696 pushConstantRanges.push_back(pushConstantRange);
697 }
698
699 return pushConstantRanges;
700 }
701
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)702 void PushConstantGraphicsDisjointInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
703 {
704 const DeviceInterface& vk = m_context.getDeviceInterface();
705 std::vector<tcu::Vec4> color (8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
706 std::vector<tcu::Vec4> allOnes (8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
707
708 switch (m_indexType)
709 {
710 case INDEX_TYPE_CONST_LITERAL:
711 // Do nothing
712 break;
713 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
714 // Stick our dynamic index at the beginning of a vector
715 color[0] = tcu::Vec4( float(DYNAMIC_VEC_INDEX),
716 float(DYNAMIC_MAT_INDEX),
717 float(DYNAMIC_ARR_INDEX),
718 1.0f);
719
720 // Place our reference values at each type offset
721
722 // vec4[i]
723 DE_ASSERT(DYNAMIC_VEC_INDEX <= 3);
724 color[1] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
725 color[1][DYNAMIC_VEC_INDEX] = DYNAMIC_VEC_CONSTANT;
726
727 // mat2[i][0]
728 DE_ASSERT(DYNAMIC_MAT_INDEX <= 1);
729 color[2] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
730 color[2][DYNAMIC_MAT_INDEX * 2] = DYNAMIC_MAT_CONSTANT;
731
732 // float[i]
733 DE_ASSERT(DYNAMIC_ARR_INDEX <= 3);
734 color[3] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
735 color[3][DYNAMIC_ARR_INDEX] = DYNAMIC_ARR_CONSTANT;
736 break;
737 default:
738 DE_FATAL("Unhandled IndexType");
739 break;
740 }
741
742 const deUint32 kind = 2u;
743 const void* value = DE_NULL;
744
745 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
746 {
747 value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
748
749 vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
750
751 if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
752 {
753 value = (void*)(&allOnes[0]);
754 vk.cmdPushConstants(cmdBuffer, pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
755 }
756 }
757 }
758
setReferenceColor(tcu::Vec4 initColor)759 void PushConstantGraphicsDisjointInstance::setReferenceColor (tcu::Vec4 initColor)
760 {
761 DE_UNREF(initColor);
762
763 const tcu::Vec4 color = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
764
765 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
766 {
767 if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
768 {
769 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
770 {
771 m_vertices[vertexNdx].color.xyzw() = color;
772 }
773 }
774 }
775 }
776
777 class PushConstantGraphicsOverlapTestInstance : public PushConstantGraphicsTestInstance
778 {
779 public:
780 PushConstantGraphicsOverlapTestInstance (Context& context,
781 const deUint32 rangeCount,
782 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
783 const deBool multipleUpdate,
784 const IndexType indexType);
785 virtual ~PushConstantGraphicsOverlapTestInstance (void);
786 std::vector<VkPushConstantRange> getPushConstantRanges (void);
787 std::vector<VkPushConstantRange> getPushConstantUpdates (void);
788 void updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout);
789 void setReferenceColor (tcu::Vec4 initColor);
790
791 private:
792 const std::vector<float> m_colorData;
793 std::vector<float> m_referenceData;
794 };
795
generateColorData(deUint32 numBytes)796 std::vector<float> generateColorData (deUint32 numBytes)
797 {
798 DE_ASSERT(numBytes % 4u == 0u);
799
800 std::vector<float> colorData;
801
802 deRandom random;
803 deRandom_init(&random, numBytes);
804
805 for (deUint32 elementNdx = 0u; elementNdx < numBytes / 4u; elementNdx++)
806 colorData.push_back(deRandom_getFloat(&random));
807
808 return colorData;
809 }
810
PushConstantGraphicsOverlapTestInstance(Context & context,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT],deBool multipleUpdate,IndexType indexType)811 PushConstantGraphicsOverlapTestInstance::PushConstantGraphicsOverlapTestInstance (Context& context,
812 const deUint32 rangeCount,
813 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
814 deBool multipleUpdate,
815 IndexType indexType)
816 : PushConstantGraphicsTestInstance (context, rangeCount, pushConstantRange, multipleUpdate, indexType)
817 , m_colorData (generateColorData(256u))
818 {
819 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
820 }
821
~PushConstantGraphicsOverlapTestInstance(void)822 PushConstantGraphicsOverlapTestInstance::~PushConstantGraphicsOverlapTestInstance(void)
823 {
824 }
825
getPushConstantRanges(void)826 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantRanges (void)
827 {
828 // Find push constant ranges for each shader stage
829 const VkShaderStageFlags shaderStages[] =
830 {
831 VK_SHADER_STAGE_VERTEX_BIT,
832 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
833 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
834 VK_SHADER_STAGE_GEOMETRY_BIT,
835 VK_SHADER_STAGE_FRAGMENT_BIT,
836 };
837
838 std::vector<VkPushConstantRange> pushConstantRanges;
839
840 m_context.getTestContext().getLog() << tcu::TestLog::Section("Ranges", "Push constant ranges");
841
842 for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(shaderStages); stageNdx++)
843 {
844 deUint32 firstByte = ~0u;
845 deUint32 lastByte = 0u;
846
847 for (deUint32 rangeNdx = 0u; rangeNdx < m_rangeCount; rangeNdx++)
848 {
849 if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStages[stageNdx])
850 {
851 firstByte = deMinu32(firstByte, m_pushConstantRange[rangeNdx].range.offset);
852 lastByte = deMaxu32(lastByte, m_pushConstantRange[rangeNdx].range.offset + m_pushConstantRange[rangeNdx].range.size);
853 }
854 }
855
856 if (firstByte != ~0u)
857 {
858 const VkPushConstantRange pushConstantRange =
859 {
860 shaderStages[stageNdx], // VkShaderStageFlags stageFlags
861 firstByte, // deUint32 offset
862 lastByte - firstByte // deUint32 size
863 };
864
865 pushConstantRanges.push_back(pushConstantRange);
866
867 m_context.getTestContext().getLog()
868 << tcu::TestLog::Message
869 << "VkShaderStageFlags stageFlags " << getShaderStageNameStr(shaderStages[stageNdx]) << ",\n"
870 << "deUint32 offset " << pushConstantRange.offset << ",\n"
871 << "deUint32 size " << pushConstantRange.size << "\n"
872 << tcu::TestLog::EndMessage;
873 }
874 }
875
876 m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
877
878 return pushConstantRanges;
879 }
880
getPushConstantUpdates(void)881 std::vector<VkPushConstantRange> PushConstantGraphicsOverlapTestInstance::getPushConstantUpdates (void)
882 {
883 VkShaderStageFlags lastStageFlags = (VkShaderStageFlags)~0u;
884 std::vector<VkPushConstantRange> pushConstantUpdates;
885
886 // Find matching shader stages for every 4 byte chunk
887 for (deUint32 offset = 0u; offset < 128u; offset += 4u)
888 {
889 VkShaderStageFlags stageFlags = (VkShaderStageFlags)0u;
890 bool updateRange = false;
891
892 // For each byte in the range specified by offset and size and for each push constant range that overlaps that byte,
893 // stageFlags must include all stages in that push constant range's VkPushConstantRange::stageFlags
894 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
895 {
896 const deUint32 rangeStart = m_pushConstantRange[rangeNdx].range.offset;
897 const deUint32 rangeEnd = rangeStart + m_pushConstantRange[rangeNdx].range.size;
898
899 const deUint32 updateStart = m_pushConstantRange[rangeNdx].update.offset;
900 const deUint32 updateEnd = updateStart + m_pushConstantRange[rangeNdx].update.size;
901
902 updateRange |= (updateStart <= offset && updateEnd >= offset + 4u);
903
904 DE_ASSERT(rangeEnd <= 128u);
905
906 if (rangeStart <= offset && rangeEnd >= offset + 4u)
907 stageFlags |= m_pushConstantRange[rangeNdx].range.shaderStage;
908 }
909
910 // Skip chunks with no updates
911 if (!stageFlags || !updateRange)
912 continue;
913
914 // Add new update entry
915 if (stageFlags != lastStageFlags)
916 {
917 const VkPushConstantRange update =
918 {
919 stageFlags, // VkShaderStageFlags stageFlags;
920 offset, // deUint32 offset;
921 4u // deUint32 size;
922 };
923
924 pushConstantUpdates.push_back(update);
925 lastStageFlags = stageFlags;
926 }
927 // Increase current update entry size
928 else
929 {
930 DE_ASSERT(pushConstantUpdates.size() > 0u);
931 pushConstantUpdates.back().size += 4u;
932 }
933 }
934
935 return pushConstantUpdates;
936 }
937
updatePushConstants(VkCommandBuffer cmdBuffer,VkPipelineLayout pipelineLayout)938 void PushConstantGraphicsOverlapTestInstance::updatePushConstants (VkCommandBuffer cmdBuffer, VkPipelineLayout pipelineLayout)
939 {
940 const DeviceInterface& vk = m_context.getDeviceInterface();
941 const std::vector<VkPushConstantRange> pushConstantUpdates = getPushConstantUpdates();
942
943 m_referenceData.resize(m_colorData.size(), 0.0f);
944
945 m_context.getTestContext().getLog() << tcu::TestLog::Section("Updates", "Push constant updates");
946
947 for (deUint32 pushNdx = 0u; pushNdx < pushConstantUpdates.size(); pushNdx++)
948 {
949 m_context.getTestContext().getLog()
950 << tcu::TestLog::Message
951 << "VkShaderStageFlags stageFlags " << getShaderStageNameStr(pushConstantUpdates[pushNdx].stageFlags) << ",\n"
952 << "deUint32 offset " << pushConstantUpdates[pushNdx].offset << ",\n"
953 << "deUint32 size " << pushConstantUpdates[pushNdx].size << ",\n"
954 << "const void* pValues " << &m_colorData[pushConstantUpdates[pushNdx].offset / 2u] << "\n"
955 << tcu::TestLog::EndMessage;
956
957 vk.cmdPushConstants(cmdBuffer, pipelineLayout, pushConstantUpdates[pushNdx].stageFlags, pushConstantUpdates[pushNdx].offset, pushConstantUpdates[pushNdx].size, &m_colorData[pushConstantUpdates[pushNdx].offset / 2u]);
958
959 // Copy push constant values to reference buffer
960 DE_ASSERT((pushConstantUpdates[pushNdx].offset / 2u + pushConstantUpdates[pushNdx].size) < 4u * m_colorData.size());
961 deMemcpy(&m_referenceData.at(pushConstantUpdates[pushNdx].offset / 4u), &m_colorData.at(pushConstantUpdates[pushNdx].offset / 2u), pushConstantUpdates[pushNdx].size);
962 }
963
964 m_context.getTestContext().getLog() << tcu::TestLog::EndSection;
965 }
966
setReferenceColor(tcu::Vec4 initColor)967 void PushConstantGraphicsOverlapTestInstance::setReferenceColor (tcu::Vec4 initColor)
968 {
969 tcu::Vec4 expectedColor = initColor;
970
971 // Calculate reference color
972 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
973 {
974 const deUint32 offset = m_pushConstantRange[rangeNdx].range.offset / 4u;
975 const deUint32 size = m_pushConstantRange[rangeNdx].range.size / 4u;
976 const deUint32 numComponents = (size < 4u) ? size : 4u;
977 const deUint32 colorNdx = (offset + size - numComponents);
978
979 for (deUint32 componentNdx = 0u; componentNdx < numComponents; componentNdx++)
980 expectedColor[componentNdx] += m_referenceData[colorNdx + componentNdx];
981 }
982
983 expectedColor = tcu::min(tcu::mod(expectedColor, tcu::Vec4(2.0f)), 2.0f - tcu::mod(expectedColor, tcu::Vec4(2.0f)));
984
985 for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
986 {
987 m_vertices[vertexNdx].color.xyzw() = expectedColor;
988 }
989 }
990
991 class PushConstantGraphicsTest : public vkt::TestCase
992 {
993 public:
994 PushConstantGraphicsTest (tcu::TestContext& testContext,
995 const std::string& name,
996 const std::string& description,
997 const deUint32 rangeCount,
998 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
999 const deBool multipleUpdate,
1000 const IndexType indexType);
1001 virtual ~PushConstantGraphicsTest (void);
1002 virtual void initPrograms (SourceCollections& sourceCollections) const = 0;
1003 virtual TestInstance* createInstance (Context& context) const = 0;
1004 RangeSizeCase getRangeSizeCase (deUint32 rangeSize) const;
1005
1006 protected:
1007 const deUint32 m_rangeCount;
1008 PushConstantData m_pushConstantRange[MAX_RANGE_COUNT];
1009 const deBool m_multipleUpdate;
1010 const IndexType m_indexType;
1011 };
1012
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)1013 PushConstantGraphicsTest::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 : vkt::TestCase (testContext, name, description)
1021 , m_rangeCount (rangeCount)
1022 , m_multipleUpdate (multipleUpdate)
1023 , m_indexType (indexType)
1024 {
1025 deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
1026 }
1027
~PushConstantGraphicsTest(void)1028 PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
1029 {
1030 }
1031
getRangeSizeCase(deUint32 rangeSize) const1032 RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
1033 {
1034 switch (rangeSize)
1035 {
1036 case 8:
1037 return SIZE_CASE_8;
1038 case 4:
1039 return SIZE_CASE_4;
1040 case 12:
1041 return SIZE_CASE_12;
1042 case 16:
1043 return SIZE_CASE_16;
1044 case 32:
1045 return SIZE_CASE_32;
1046 case 36:
1047 return SIZE_CASE_36;
1048 case 48:
1049 return SIZE_CASE_48;
1050 case 128:
1051 return SIZE_CASE_128;
1052 default:
1053 DE_FATAL("Range size unsupported yet");
1054 return SIZE_CASE_UNSUPPORTED;
1055 }
1056 }
1057
1058 class PushConstantGraphicsDisjointTest : public PushConstantGraphicsTest
1059 {
1060 public:
1061 PushConstantGraphicsDisjointTest (tcu::TestContext& testContext,
1062 const std::string& name,
1063 const std::string& description,
1064 const deUint32 rangeCount,
1065 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
1066 const deBool multipleUpdate,
1067 const IndexType indexType);
1068 virtual ~PushConstantGraphicsDisjointTest (void);
1069 virtual void initPrograms (SourceCollections& sourceCollections) const;
1070 virtual TestInstance* createInstance (Context& context) const;
1071 };
1072
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)1073 PushConstantGraphicsDisjointTest::PushConstantGraphicsDisjointTest (tcu::TestContext& testContext,
1074 const std::string& name,
1075 const std::string& description,
1076 const deUint32 rangeCount,
1077 const PushConstantData pushConstantRange[MAX_RANGE_COUNT],
1078 const deBool multipleUpdate,
1079 const IndexType indexType)
1080 : PushConstantGraphicsTest (testContext, name, description, rangeCount, pushConstantRange, multipleUpdate, indexType)
1081 {
1082 }
1083
~PushConstantGraphicsDisjointTest(void)1084 PushConstantGraphicsDisjointTest::~PushConstantGraphicsDisjointTest (void)
1085 {
1086 }
1087
initPrograms(SourceCollections & sourceCollections) const1088 void PushConstantGraphicsDisjointTest::initPrograms (SourceCollections& sourceCollections) const
1089 {
1090 std::ostringstream vertexSrc;
1091 std::ostringstream fragmentSrc;
1092 std::ostringstream geometrySrc;
1093 std::ostringstream tessControlSrc;
1094 std::ostringstream tessEvaluationSrc;
1095
1096 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1097 {
1098 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1099 {
1100 vertexSrc << "#version 450\n"
1101 << "layout(location = 0) in highp vec4 position;\n"
1102 << "layout(location = 1) in highp vec4 color;\n"
1103 << "layout(location = 0) out highp vec4 vtxColor;\n"
1104 << "out gl_PerVertex { vec4 gl_Position; };\n"
1105 << "layout(push_constant) uniform Material {\n";
1106
1107 switch (m_indexType)
1108 {
1109 case INDEX_TYPE_CONST_LITERAL:
1110 switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1111 {
1112 case SIZE_CASE_4:
1113 vertexSrc << "int kind;\n"
1114 << "} matInst;\n";
1115 break;
1116 case SIZE_CASE_16:
1117 vertexSrc << "vec4 color;\n"
1118 << "} matInst;\n"
1119 << "layout(std140, binding = 0) uniform UniformBuf {\n"
1120 << "vec4 element;\n"
1121 << "} uniformBuf;\n";
1122 break;
1123 case SIZE_CASE_32:
1124 vertexSrc << "vec4 color[2];\n"
1125 << "} matInst;\n";
1126 break;
1127 case SIZE_CASE_48:
1128 vertexSrc << "int dummy1;\n"
1129 << "vec4 dummy2;\n"
1130 << "vec4 color;\n"
1131 << "} matInst;\n";
1132 break;
1133 case SIZE_CASE_128:
1134 vertexSrc << "vec4 color[8];\n"
1135 << "} matInst;\n";
1136 break;
1137 default:
1138 DE_FATAL("Not implemented yet");
1139 break;
1140 }
1141 break;
1142 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1143 vertexSrc << " layout(offset = 0) vec4 index; \n"
1144 << " layout(offset = 16) vec4 vecType; \n"
1145 << " layout(offset = 32) mat2 matType; \n"
1146 << " layout(offset = 48) float[4] arrType; \n"
1147 << "} matInst;\n";
1148 break;
1149 default:
1150 DE_FATAL("Unhandled IndexType");
1151 break;
1152 }
1153
1154 vertexSrc << "void main()\n"
1155 << "{\n"
1156 << " gl_Position = position;\n";
1157
1158 switch (m_indexType)
1159 {
1160 case INDEX_TYPE_CONST_LITERAL:
1161 switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1162 {
1163 case SIZE_CASE_4:
1164 vertexSrc << "switch (matInst.kind) {\n"
1165 << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
1166 << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
1167 << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
1168 << "default: vtxColor = color; break;}\n"
1169 << "}\n";
1170 break;
1171 case SIZE_CASE_16:
1172 vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
1173 << "}\n";
1174 break;
1175 case SIZE_CASE_32:
1176 vertexSrc << "vtxColor = (matInst.color[0] + matInst.color[1]) * 0.5;\n"
1177 << "}\n";
1178 break;
1179 case SIZE_CASE_48:
1180 vertexSrc << "vtxColor = matInst.color;\n"
1181 << "}\n";
1182 break;
1183 case SIZE_CASE_128:
1184 vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
1185 << "for (int i = 0; i < 8; i++)\n"
1186 << "{\n"
1187 << " color = color + matInst.color[i];\n"
1188 << "}\n"
1189 << "vtxColor = color * 0.125;\n"
1190 << "}\n";
1191 break;
1192 default:
1193 DE_FATAL("Not implemented yet");
1194 break;
1195 }
1196 break;
1197 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1198 {
1199 vertexSrc << " vtxColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1200 // Mix in gl_Position to (hopefully) prevent optimizing our index away
1201 << " int vec_selector = int(abs(gl_Position.x) * 0.0000001 + 0);\n"
1202 << " int mat_selector = int(abs(gl_Position.x) * 0.0000001 + 1);\n"
1203 << " int arr_selector = int(abs(gl_Position.x) * 0.0000001 + 2);\n";
1204
1205 // Use the dynamic index to pull our real index value from push constants
1206 // Then use that value to index into three variable types
1207 std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1208 std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1209 std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1210
1211 // Test vector indexing
1212 vertexSrc << " if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1213 << " vtxColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1214
1215 // Test matrix indexing
1216 vertexSrc << " if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1217 << " vtxColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1218
1219 // Test array indexing
1220 vertexSrc << " if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1221 << " vtxColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1222
1223 vertexSrc << "}\n";
1224 }
1225 break;
1226 default:
1227 DE_FATAL("Unhandled IndexType");
1228 break;
1229 }
1230
1231 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
1232 }
1233
1234 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1235 {
1236 tessControlSrc << "#version 450\n"
1237 << "layout (vertices = 3) out;\n"
1238 << "layout(push_constant) uniform TessLevel {\n"
1239 << " layout(offset = 24) int level;\n"
1240 << "} tessLevel;\n"
1241 << "layout(location = 0) in highp vec4 color[];\n"
1242 << "layout(location = 0) out highp vec4 vtxColor[];\n"
1243 << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1244 << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
1245 << "void main()\n"
1246 << "{\n"
1247 << " gl_TessLevelInner[0] = tessLevel.level;\n"
1248 << " gl_TessLevelOuter[0] = tessLevel.level;\n"
1249 << " gl_TessLevelOuter[1] = tessLevel.level;\n"
1250 << " gl_TessLevelOuter[2] = tessLevel.level;\n"
1251 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1252 << " vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1253 << "}\n";
1254
1255 sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
1256 }
1257
1258 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1259 {
1260 tessEvaluationSrc << "#version 450\n"
1261 << "layout (triangles) in;\n"
1262 << "layout(push_constant) uniform Material {\n"
1263 << " layout(offset = 32) vec4 color;\n"
1264 << "} matInst;\n"
1265 << "layout(location = 0) in highp vec4 color[];\n"
1266 << "layout(location = 0) out highp vec4 vtxColor;\n"
1267 << "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
1268 << "out gl_PerVertex { vec4 gl_Position; };\n"
1269 << "void main()\n"
1270 << "{\n"
1271 << " 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"
1272 << " vtxColor = matInst.color;\n"
1273 << "}\n";
1274
1275 sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
1276 }
1277
1278 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1279 {
1280 geometrySrc << "#version 450\n"
1281 << "layout(triangles) in;\n"
1282 << "layout(triangle_strip, max_vertices=3) out;\n"
1283 << "layout(push_constant) uniform Material {\n"
1284 << " layout(offset = 20) int kind;\n"
1285 << "} matInst;\n"
1286 << "layout(location = 0) in highp vec4 color[];\n"
1287 << "layout(location = 0) out highp vec4 vtxColor;\n"
1288 << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
1289 << "out gl_PerVertex { vec4 gl_Position; };\n"
1290 << "void main()\n"
1291 << "{\n"
1292 << " for(int i=0; i<3; i++)\n"
1293 << " {\n"
1294 << " gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
1295 << " gl_Position.w = gl_in[i].gl_Position.w;\n"
1296 << " vtxColor = color[i];\n"
1297 << " EmitVertex();\n"
1298 << " }\n"
1299 << " EndPrimitive();\n"
1300 << "}\n";
1301
1302 sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
1303 }
1304
1305 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1306 {
1307 fragmentSrc << "#version 450\n"
1308 << "layout(location = 0) in highp vec4 vtxColor;\n"
1309 << "layout(location = 0) out highp vec4 fragColor;\n"
1310 << "layout(push_constant) uniform Material {\n";
1311
1312 switch (m_indexType)
1313 {
1314 case INDEX_TYPE_CONST_LITERAL:
1315 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1316 {
1317 fragmentSrc << " layout(offset = 0) int kind; \n"
1318 << "} matInst;\n";
1319 }
1320 else
1321 {
1322 fragmentSrc << " layout(offset = 16) int kind;\n"
1323 << "} matInst;\n";
1324 }
1325
1326 fragmentSrc << "void main (void)\n"
1327 << "{\n"
1328 << " switch (matInst.kind) {\n"
1329 << " case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
1330 << " case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
1331 << " case 2: fragColor = vtxColor; break;\n"
1332 << " default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
1333 << "}\n";
1334 break;
1335 case INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR:
1336 {
1337 fragmentSrc << " layout(offset = 0) vec4 index; \n"
1338 << " layout(offset = 16) vec4 vecType; \n"
1339 << " layout(offset = 32) mat2 matType; \n"
1340 << " layout(offset = 48) float[4] arrType; \n"
1341 << "} matInst;\n";
1342
1343 fragmentSrc << "void main (void)\n"
1344 << "{\n"
1345 << " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
1346
1347 // Mix in gl_FragCoord to (hopefully) prevent optimizing our index away
1348 << " int vec_selector = int(gl_FragCoord.x * 0.0000001 + 0);\n"
1349 << " int mat_selector = int(gl_FragCoord.x * 0.0000001 + 1);\n"
1350 << " int arr_selector = int(gl_FragCoord.x * 0.0000001 + 2);\n";
1351
1352 // Use the dynamic index to pull our real index value from push constants
1353 // Then use that value to index into three variable types
1354 std::string vecValue = "matInst.vecType[int(matInst.index[vec_selector])]";
1355 std::string matValue = "matInst.matType[int(matInst.index[mat_selector])][0]";
1356 std::string arrValue = "matInst.arrType[int(matInst.index[arr_selector])]";
1357
1358 // Test vector indexing
1359 fragmentSrc << " if (" << vecValue << " != " << DYNAMIC_VEC_CONSTANT << ")\n"
1360 << " fragColor += vec4(0.0, 0.5, 0.0, 1.0);\n";
1361
1362 // Test matrix indexing
1363 fragmentSrc << " if (" << matValue << " != " << DYNAMIC_MAT_CONSTANT << ")\n"
1364 << " fragColor += vec4(0.0, 0.0, 0.5, 1.0);\n";
1365
1366 // Test array indexing
1367 fragmentSrc << " if (" << arrValue << " != " << DYNAMIC_ARR_CONSTANT << ")\n"
1368 << " fragColor = vec4(0.0, 0.5, 0.5, 1.0);\n";
1369
1370 fragmentSrc << "}\n";
1371 }
1372 break;
1373 default:
1374 DE_FATAL("Unhandled IndexType");
1375 break;
1376 }
1377
1378 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1379 }
1380 }
1381
1382 // add a pass through fragment shader if it's not activated in push constant ranges
1383 if (fragmentSrc.str().empty())
1384 {
1385 fragmentSrc << "#version 450\n"
1386 << "layout(location = 0) in highp vec4 vtxColor;\n"
1387 << "layout(location = 0) out highp vec4 fragColor;\n"
1388 << "void main (void)\n"
1389 << "{\n"
1390 << " fragColor = vtxColor;\n"
1391 << "}\n";
1392
1393 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
1394 }
1395 }
1396
createInstance(Context & context) const1397 TestInstance* PushConstantGraphicsDisjointTest::createInstance (Context& context) const
1398 {
1399 return new PushConstantGraphicsDisjointInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate, m_indexType);
1400 }
1401
1402 class PushConstantGraphicsOverlapTest : public PushConstantGraphicsTest
1403 {
1404 public:
1405 PushConstantGraphicsOverlapTest (tcu::TestContext& testContext,
1406 const std::string& name,
1407 const std::string& description,
1408 const deUint32 rangeCount,
1409 const PushConstantData pushConstantRange[MAX_RANGE_COUNT]);
1410 virtual ~PushConstantGraphicsOverlapTest (void);
1411 std::string getPushConstantDeclarationStr (VkShaderStageFlags shaderStage) const;
1412 virtual void initPrograms (SourceCollections& sourceCollections) const;
1413 virtual TestInstance* createInstance (Context& context) const;
1414 };
1415
PushConstantGraphicsOverlapTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const deUint32 rangeCount,const PushConstantData pushConstantRange[MAX_RANGE_COUNT])1416 PushConstantGraphicsOverlapTest::PushConstantGraphicsOverlapTest (tcu::TestContext& testContext,
1417 const std::string& name,
1418 const std::string& description,
1419 const deUint32 rangeCount,
1420 const PushConstantData pushConstantRange[MAX_RANGE_COUNT])
1421 : PushConstantGraphicsTest (testContext, name, description, rangeCount, pushConstantRange, false, INDEX_TYPE_CONST_LITERAL)
1422 {
1423 }
1424
~PushConstantGraphicsOverlapTest(void)1425 PushConstantGraphicsOverlapTest::~PushConstantGraphicsOverlapTest (void)
1426 {
1427 }
1428
getPushConstantDeclarationStr(VkShaderStageFlags shaderStage) const1429 std::string PushConstantGraphicsOverlapTest::getPushConstantDeclarationStr (VkShaderStageFlags shaderStage) const
1430 {
1431 std::stringstream src;
1432
1433 src << "layout(push_constant) uniform Material\n"
1434 << "{\n";
1435
1436 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1437 {
1438 if (m_pushConstantRange[rangeNdx].range.shaderStage & shaderStage)
1439 {
1440 switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
1441 {
1442 case SIZE_CASE_4:
1443 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") float color;\n";
1444 break;
1445 case SIZE_CASE_8:
1446 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec2 color;\n";
1447 break;
1448 case SIZE_CASE_12:
1449 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec3 color;\n";
1450 break;
1451 case SIZE_CASE_16:
1452 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color;\n";
1453 break;
1454 case SIZE_CASE_32:
1455 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[2];\n";
1456 break;
1457 case SIZE_CASE_36:
1458 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") int dummy1;\n"
1459 << " layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 4) << ") vec4 dummy2;\n"
1460 << " layout(offset = " << (m_pushConstantRange[rangeNdx].range.offset + 20) << ") vec4 color;\n";
1461 break;
1462 case SIZE_CASE_128:
1463 src << " layout(offset = " << m_pushConstantRange[rangeNdx].range.offset << ") vec4 color[8];\n";
1464 break;
1465 default:
1466 DE_FATAL("Not implemented");
1467 break;
1468 }
1469 }
1470 }
1471
1472 src << "} matInst;\n";
1473
1474 return src.str();
1475 }
1476
getSwizzleStr(deUint32 size)1477 std::string getSwizzleStr (deUint32 size)
1478 {
1479 switch (size)
1480 {
1481 case 4: return ".x";
1482 case 8: return ".xy";
1483 case 12: return ".xyz";
1484 case 16:
1485 case 32:
1486 case 36:
1487 case 128: return "";
1488 default: DE_FATAL("Not implemented");
1489 return "";
1490 }
1491 }
1492
getColorReadStr(deUint32 size)1493 std::string getColorReadStr (deUint32 size)
1494 {
1495 // Always read the last element from array types
1496 const std::string arrayNdx = (size == 128u) ? "[7]"
1497 : (size == 32u) ? "[1]"
1498 : "";
1499 const std::string colorReadStr = getSwizzleStr(size) + " += matInst.color" + arrayNdx + ";\n";;
1500
1501 return colorReadStr;
1502 }
1503
initPrograms(SourceCollections & sourceCollections) const1504 void PushConstantGraphicsOverlapTest::initPrograms (SourceCollections& sourceCollections) const
1505 {
1506 for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
1507 {
1508 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
1509 {
1510 const std::string source =
1511 "#version 450\n"
1512 "layout(location = 0) in highp vec4 position;\n"
1513 "layout(location = 1) in highp vec4 inColor;\n"
1514 "layout(location = 0) out highp vec4 vtxColor;\n"
1515 "out gl_PerVertex\n"
1516 "{\n"
1517 " vec4 gl_Position;\n"
1518 "};\n"
1519 + getPushConstantDeclarationStr(VK_SHADER_STAGE_VERTEX_BIT) +
1520 "void main()\n"
1521 "{\n"
1522 " gl_Position = position;\n"
1523 " vec4 color = inColor;\n"
1524 " color" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1525 " vtxColor = color;\n"
1526 "}\n";
1527
1528 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(source);
1529 }
1530
1531 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1532 {
1533 const std::string source =
1534 "#version 450\n"
1535 "layout (vertices = 3) out;\n"
1536 + getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) +
1537 "layout(location = 0) in highp vec4 color[];\n"
1538 "layout(location = 0) out highp vec4 vtxColor[];\n"
1539 "in gl_PerVertex\n"
1540 "{\n"
1541 " vec4 gl_Position;\n"
1542 "} gl_in[gl_MaxPatchVertices];\n"
1543 "out gl_PerVertex\n"
1544 "{\n"
1545 " vec4 gl_Position;\n"
1546 "} gl_out[];\n"
1547 "void main()\n"
1548 "{\n"
1549 " gl_TessLevelInner[0] = 2.0;\n"
1550 " gl_TessLevelOuter[0] = 2.0;\n"
1551 " gl_TessLevelOuter[1] = 2.0;\n"
1552 " gl_TessLevelOuter[2] = 2.0;\n"
1553 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1554 " vec4 outColor = color[gl_InvocationID];\n"
1555 " outColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1556 " vtxColor[gl_InvocationID] = outColor;\n"
1557 "}\n";
1558
1559 sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(source);
1560 }
1561
1562 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1563 {
1564 const std::string source =
1565 "#version 450\n"
1566 "layout (triangles) in;\n"
1567 + getPushConstantDeclarationStr(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) +
1568 "layout(location = 0) in highp vec4 color[];\n"
1569 "layout(location = 0) out highp vec4 vtxColor;\n"
1570 "in gl_PerVertex\n"
1571 "{\n"
1572 " vec4 gl_Position;\n"
1573 "} gl_in[gl_MaxPatchVertices];\n"
1574 "out gl_PerVertex\n"
1575 "{\n"
1576 " vec4 gl_Position;\n"
1577 "};\n"
1578 "void main()\n"
1579 "{\n"
1580 " 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"
1581 " vtxColor = gl_TessCoord.x * color[0] + gl_TessCoord.y * color[1] + gl_TessCoord.z * color[2];\n"
1582 " vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1583 "}\n";
1584
1585 sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(source);
1586 }
1587
1588 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
1589 {
1590 const std::string source =
1591 "#version 450\n"
1592 "layout(triangles) in;\n"
1593 "layout(triangle_strip, max_vertices=3) out;\n"
1594 + getPushConstantDeclarationStr(VK_SHADER_STAGE_GEOMETRY_BIT) +
1595 "layout(location = 0) in highp vec4 color[];\n"
1596 "layout(location = 0) out highp vec4 vtxColor;\n"
1597 "in gl_PerVertex\n"
1598 "{\n"
1599 " vec4 gl_Position;\n"
1600 "} gl_in[];\n"
1601 "out gl_PerVertex\n"
1602 "{\n"
1603 " vec4 gl_Position;\n"
1604 "};\n"
1605 "void main()\n"
1606 "{\n"
1607 " for(int i = 0; i < 3; i++)\n"
1608 " {\n"
1609 " gl_Position.xyz = gl_in[i].gl_Position.xyz / 2.0;\n"
1610 " gl_Position.w = gl_in[i].gl_Position.w;\n"
1611 " vtxColor = color[i];\n"
1612 " vtxColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1613 " EmitVertex();\n"
1614 " }\n"
1615 " EndPrimitive();\n"
1616 "}\n";
1617
1618 sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(source);
1619 }
1620
1621 if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
1622 {
1623 const std::string source =
1624 "#version 450\n"
1625 "layout(location = 0) in highp vec4 vtxColor;\n"
1626 "layout(location = 0) out highp vec4 fragColor;\n"
1627 + getPushConstantDeclarationStr(VK_SHADER_STAGE_FRAGMENT_BIT) +
1628 "void main (void)\n"
1629 "{\n"
1630 " fragColor = vtxColor;\n"
1631 " fragColor" + getColorReadStr(m_pushConstantRange[rangeNdx].range.size) +
1632 " fragColor = min(mod(fragColor, 2.0), 2.0 - mod(fragColor, 2.0));\n"
1633 "}\n";
1634
1635 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(source);
1636 }
1637 }
1638 }
1639
createInstance(Context & context) const1640 TestInstance* PushConstantGraphicsOverlapTest::createInstance (Context& context) const
1641 {
1642 return new PushConstantGraphicsOverlapTestInstance(context, m_rangeCount, m_pushConstantRange, false, INDEX_TYPE_CONST_LITERAL);
1643 }
1644
1645 class PushConstantComputeTest : public vkt::TestCase
1646 {
1647 public:
1648 PushConstantComputeTest (tcu::TestContext& testContext,
1649 const std::string& name,
1650 const std::string& description,
1651 const PushConstantData pushConstantRange);
1652 virtual ~PushConstantComputeTest (void);
1653 virtual void initPrograms (SourceCollections& sourceCollections) const;
1654 virtual TestInstance* createInstance (Context& context) const;
1655
1656 private:
1657 const PushConstantData m_pushConstantRange;
1658 };
1659
1660 class PushConstantComputeTestInstance : public vkt::TestInstance
1661 {
1662 public:
1663 PushConstantComputeTestInstance (Context& context,
1664 const PushConstantData pushConstantRange);
1665 virtual ~PushConstantComputeTestInstance (void);
1666 virtual tcu::TestStatus iterate (void);
1667
1668 private:
1669 const PushConstantData m_pushConstantRange;
1670
1671 Move<VkBuffer> m_outBuffer;
1672 de::MovePtr<Allocation> m_outBufferAlloc;
1673 Move<VkDescriptorPool> m_descriptorPool;
1674 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1675 Move<VkDescriptorSet> m_descriptorSet;
1676
1677 Move<VkPipelineLayout> m_pipelineLayout;
1678 Move<VkPipeline> m_computePipelines;
1679
1680 Move<VkShaderModule> m_computeShaderModule;
1681
1682 Move<VkCommandPool> m_cmdPool;
1683 Move<VkCommandBuffer> m_cmdBuffer;
1684 };
1685
PushConstantComputeTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const PushConstantData pushConstantRange)1686 PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext& testContext,
1687 const std::string& name,
1688 const std::string& description,
1689 const PushConstantData pushConstantRange)
1690 : vkt::TestCase (testContext, name, description)
1691 , m_pushConstantRange (pushConstantRange)
1692 {
1693 }
1694
~PushConstantComputeTest(void)1695 PushConstantComputeTest::~PushConstantComputeTest (void)
1696 {
1697 }
1698
createInstance(Context & context) const1699 TestInstance* PushConstantComputeTest::createInstance (Context& context) const
1700 {
1701 return new PushConstantComputeTestInstance(context, m_pushConstantRange);
1702 }
1703
initPrograms(SourceCollections & sourceCollections) const1704 void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
1705 {
1706 std::ostringstream computeSrc;
1707
1708 computeSrc << "#version 450\n"
1709 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1710 << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
1711 << " vec4 elements[];\n"
1712 << "} outData;\n"
1713 << "layout(push_constant) uniform Material{\n"
1714 << " vec4 element;\n"
1715 << "} matInst;\n"
1716 << "void main (void)\n"
1717 << "{\n"
1718 << " outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
1719 << "}\n";
1720
1721 sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
1722 }
1723
PushConstantComputeTestInstance(Context & context,const PushConstantData pushConstantRange)1724 PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context& context,
1725 const PushConstantData pushConstantRange)
1726 : vkt::TestInstance (context)
1727 , m_pushConstantRange (pushConstantRange)
1728 {
1729 const DeviceInterface& vk = context.getDeviceInterface();
1730 const VkDevice vkDevice = context.getDevice();
1731 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
1732 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
1733
1734 // Create pipeline layout
1735 {
1736 // create push constant range
1737 VkPushConstantRange pushConstantRanges;
1738 pushConstantRanges.stageFlags = m_pushConstantRange.range.shaderStage;
1739 pushConstantRanges.offset = m_pushConstantRange.range.offset;
1740 pushConstantRanges.size = m_pushConstantRange.range.size;
1741
1742 // create descriptor set layout
1743 m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
1744
1745 // create descriptor pool
1746 m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1747
1748 // create uniform buffer
1749 const VkDeviceSize bufferSize = sizeof(tcu::Vec4) * 8;
1750 const VkBufferCreateInfo bufferCreateInfo =
1751 {
1752 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1753 DE_NULL, // const void* pNext;
1754 0u, // VkBufferCreateFlags flags
1755 bufferSize, // VkDeviceSize size;
1756 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // VkBufferUsageFlags usage;
1757 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1758 1u, // deUint32 queueFamilyCount;
1759 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1760 };
1761
1762 m_outBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
1763 m_outBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
1764 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
1765
1766 // create and update descriptor set
1767 const VkDescriptorSetAllocateInfo allocInfo =
1768 {
1769 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
1770 DE_NULL, // const void* pNext;
1771 *m_descriptorPool, // VkDescriptorPool descriptorPool;
1772 1u, // uint32_t setLayoutCount;
1773 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
1774 };
1775 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
1776
1777 const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
1778
1779 DescriptorSetUpdateBuilder()
1780 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
1781 .update(vk, vkDevice);
1782
1783 // create pipeline layout
1784 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1785 {
1786 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1787 DE_NULL, // const void* pNext;
1788 0u, // VkPipelineLayoutCreateFlags flags;
1789 1u, // deUint32 descriptorSetCount;
1790 &(*m_descriptorSetLayout), // const VkDescriptorSetLayout* pSetLayouts;
1791 1u, // deUint32 pushConstantRangeCount;
1792 &pushConstantRanges // const VkPushConstantRange* pPushConstantRanges;
1793 };
1794
1795 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1796 }
1797
1798 // create pipeline
1799 {
1800 m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
1801
1802 const VkPipelineShaderStageCreateInfo stageCreateInfo =
1803 {
1804 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1805 DE_NULL, // const void* pNext;
1806 0u, // VkPipelineShaderStageCreateFlags flags;
1807 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1808 *m_computeShaderModule, // VkShaderModule module;
1809 "main", // const char* pName;
1810 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1811 };
1812
1813 const VkComputePipelineCreateInfo createInfo =
1814 {
1815 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1816 DE_NULL, // const void* pNext;
1817 0u, // VkPipelineCreateFlags flags;
1818 stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
1819 *m_pipelineLayout, // VkPipelineLayout layout;
1820 (VkPipeline)0, // VkPipeline basePipelineHandle;
1821 0u, // int32_t basePipelineIndex;
1822 };
1823
1824 m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
1825 }
1826
1827 // Create command pool
1828 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1829
1830 // Create command buffer
1831 {
1832 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1833
1834 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1835
1836 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
1837 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
1838
1839 // update push constant
1840 tcu::Vec4 value = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
1841 vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
1842
1843 vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
1844
1845 endCommandBuffer(vk, *m_cmdBuffer);
1846 }
1847 }
1848
~PushConstantComputeTestInstance(void)1849 PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
1850 {
1851 }
1852
iterate(void)1853 tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
1854 {
1855 const DeviceInterface& vk = m_context.getDeviceInterface();
1856 const VkDevice vkDevice = m_context.getDevice();
1857 const VkQueue queue = m_context.getUniversalQueue();
1858
1859 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1860
1861 invalidateAlloc(vk, vkDevice, *m_outBufferAlloc);
1862
1863 // verify result
1864 std::vector<tcu::Vec4> expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
1865 if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
1866 {
1867 return tcu::TestStatus::fail("Image mismatch");
1868 }
1869 return tcu::TestStatus::pass("result image matches with reference");
1870 }
1871
1872 } // anonymous
1873
createPushConstantTests(tcu::TestContext & testCtx)1874 tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
1875 {
1876 static const struct
1877 {
1878 const char* name;
1879 const char* description;
1880 deUint32 count;
1881 PushConstantData range[MAX_RANGE_COUNT];
1882 deBool hasMultipleUpdates;
1883 IndexType indexType;
1884 } graphicsParams[] =
1885 {
1886 // test range size from minimum valid size to maximum
1887 {
1888 "range_size_4",
1889 "test range size is 4 bytes(minimum valid size)",
1890 1u,
1891 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
1892 false,
1893 INDEX_TYPE_CONST_LITERAL
1894 },
1895 {
1896 "range_size_16",
1897 "test range size is 16 bytes, and together with a normal uniform",
1898 1u,
1899 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
1900 false,
1901 INDEX_TYPE_CONST_LITERAL
1902 },
1903 {
1904 "range_size_128",
1905 "test range size is 128 bytes(maximum valid size)",
1906 1u,
1907 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
1908 false,
1909 INDEX_TYPE_CONST_LITERAL
1910 },
1911 // test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
1912 {
1913 "count_2_shaders_vert_frag",
1914 "test range count is 2, use vertex and fragment shaders",
1915 2u,
1916 {
1917 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1918 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1919 },
1920 false,
1921 INDEX_TYPE_CONST_LITERAL
1922 },
1923 {
1924 "count_3_shaders_vert_geom_frag",
1925 "test range count is 3, use vertex, geometry and fragment shaders",
1926 3u,
1927 {
1928 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1929 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1930 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1931 },
1932 false,
1933 INDEX_TYPE_CONST_LITERAL
1934 },
1935 {
1936 "count_5_shaders_vert_tess_geom_frag",
1937 "test range count is 5, use vertex, tessellation, geometry and fragment shaders",
1938 5u,
1939 {
1940 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
1941 { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
1942 { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
1943 { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
1944 { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 32, 16 }, { 32, 16 } },
1945 },
1946 false,
1947 INDEX_TYPE_CONST_LITERAL
1948 },
1949 {
1950 "count_1_shader_vert_frag",
1951 "test range count is 1, vertex and fragment shaders share one range",
1952 1u,
1953 { { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
1954 false,
1955 INDEX_TYPE_CONST_LITERAL
1956 },
1957 // test data partial update and multiple times update
1958 {
1959 "data_update_partial_1",
1960 "test partial update of the values",
1961 1u,
1962 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 32 }, { 4, 24 } } },
1963 false,
1964 INDEX_TYPE_CONST_LITERAL
1965 },
1966 {
1967 "data_update_partial_2",
1968 "test partial update of the values",
1969 1u,
1970 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 48 }, { 32, 16 } } },
1971 false,
1972 INDEX_TYPE_CONST_LITERAL
1973 },
1974 {
1975 "data_update_multiple",
1976 "test multiple times update of the values",
1977 1u,
1978 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
1979 true,
1980 INDEX_TYPE_CONST_LITERAL
1981 },
1982 {
1983 "dynamic_index_vert",
1984 "dynamically uniform indexing of vertex, matrix, and array in vertex shader",
1985 1u,
1986 { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 64 }, { 0, 64 } } },
1987 false,
1988 INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
1989 },
1990 {
1991 "dynamic_index_frag",
1992 "dynamically uniform indexing of vertex, matrix, and array in fragment shader",
1993 1u,
1994 { { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 64 }, { 0, 64 } } },
1995 false,
1996 INDEX_TYPE_DYNAMICALLY_UNIFORM_EXPR
1997 }
1998 };
1999
2000 static const struct
2001 {
2002 const char* name;
2003 const char* description;
2004 deUint32 count;
2005 PushConstantData range[MAX_RANGE_COUNT];
2006 } overlapGraphicsParams[] =
2007 {
2008 // test ranges with multiple overlapping stages
2009 {
2010 "overlap_2_shaders_vert_frag",
2011 "overlapping range count is 2, use vertex and fragment shaders",
2012 2u,
2013 {
2014 { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
2015 { { VK_SHADER_STAGE_FRAGMENT_BIT, 12, 36 }, { 12, 36 } },
2016 }
2017 },
2018 {
2019 "overlap_3_shaders_vert_geom_frag",
2020 "overlapping range count is 3, use vertex, geometry and fragment shaders",
2021 3u,
2022 {
2023 { { VK_SHADER_STAGE_VERTEX_BIT, 12, 36 }, { 12, 36 } },
2024 { { VK_SHADER_STAGE_GEOMETRY_BIT, 0, 32 }, { 16, 16 } },
2025 { { VK_SHADER_STAGE_FRAGMENT_BIT, 20, 4 }, { 20, 4 } }
2026 }
2027 },
2028 {
2029 "overlap_4_shaders_vert_tess_frag",
2030 "overlapping range count is 4, use vertex, tessellation and fragment shaders",
2031 4u,
2032 {
2033 { { VK_SHADER_STAGE_VERTEX_BIT, 8, 4 }, { 8, 4 } },
2034 { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0, 128 }, { 52, 76 } },
2035 { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 56, 8 }, { 56, 8 } },
2036 { { VK_SHADER_STAGE_FRAGMENT_BIT, 60, 36 }, { 60, 36 } }
2037 }
2038 },
2039 {
2040 "overlap_5_shaders_vert_tess_geom_frag",
2041 "overlapping range count is 5, use vertex, tessellation, geometry and fragment shaders",
2042 5u,
2043 {
2044 { { VK_SHADER_STAGE_VERTEX_BIT, 40, 8 }, { 40, 8 } },
2045 { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 32, 12 }, { 32, 12 } },
2046 { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 48, 16 }, { 48, 16 } },
2047 { { VK_SHADER_STAGE_GEOMETRY_BIT, 28, 36 }, { 28, 36 } },
2048 { { VK_SHADER_STAGE_FRAGMENT_BIT, 56, 8 }, { 60, 4 } }
2049 }
2050 }
2051 };
2052
2053 static const struct
2054 {
2055 const char* name;
2056 const char* description;
2057 PushConstantData range;
2058 } computeParams[] =
2059 {
2060 {
2061 "simple_test",
2062 "test compute pipeline",
2063 { { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
2064 },
2065 };
2066
2067 de::MovePtr<tcu::TestCaseGroup> pushConstantTests (new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
2068
2069 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
2070 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
2071 {
2072 graphicsTests->addChild(new PushConstantGraphicsDisjointTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates, graphicsParams[ndx].indexType));
2073 }
2074
2075 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(overlapGraphicsParams); ndx++)
2076 {
2077 graphicsTests->addChild(new PushConstantGraphicsOverlapTest(testCtx, overlapGraphicsParams[ndx].name, overlapGraphicsParams[ndx].description, overlapGraphicsParams[ndx].count, overlapGraphicsParams[ndx].range));
2078 }
2079 pushConstantTests->addChild(graphicsTests.release());
2080
2081 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
2082 computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
2083 pushConstantTests->addChild(computeTests.release());
2084
2085 return pushConstantTests.release();
2086 }
2087
2088 } // pipeline
2089 } // vkt
2090