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