1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Intel Corporation 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 Dynamic State Tests - Base Class 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktDynamicStateBaseClass.hpp" 28 29#include "vkPrograms.hpp" 30#include "vkTypeUtil.hpp" 31#include "vkCmdUtil.hpp" 32#include "vkObjUtil.hpp" 33#include "vkBuilderUtil.hpp" 34#include "vkBarrierUtil.hpp" 35 36namespace vkt 37{ 38namespace DynamicState 39{ 40 41using namespace Draw; 42 43DynamicStateBaseClass::DynamicStateBaseClass (Context& context, 44 vk::PipelineConstructionType pipelineConstructionType, 45 const char* vertexShaderName, 46 const char* fragmentShaderName, 47 const char* meshShaderName) 48 : TestInstance (context) 49 , m_pipelineConstructionType (pipelineConstructionType) 50 , m_colorAttachmentFormat (vk::VK_FORMAT_R8G8B8A8_UNORM) 51 , m_topology (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) 52 , m_vk (context.getDeviceInterface()) 53 , m_pipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType) 54 , m_vertexShaderName (vertexShaderName ? vertexShaderName : "") 55 , m_fragmentShaderName (fragmentShaderName) 56 , m_meshShaderName (meshShaderName ? meshShaderName : "") 57 , m_isMesh (meshShaderName != nullptr) 58{ 59 // We must provide either the mesh shader or the vertex shader. 60 DE_ASSERT(static_cast<bool>(vertexShaderName) != static_cast<bool>(meshShaderName)); 61} 62 63void DynamicStateBaseClass::initialize (void) 64{ 65 const vk::VkDevice device = m_context.getDevice(); 66 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 67 const auto vertDescType = (m_isMesh ? vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : vk::VK_DESCRIPTOR_TYPE_MAX_ENUM); 68 std::vector<vk::VkPushConstantRange> pcRanges; 69 70 // The mesh shading pipeline will contain a set with vertex data. 71#ifndef CTS_USES_VULKANSC 72 if (m_isMesh) 73 { 74 vk::DescriptorSetLayoutBuilder setLayoutBuilder; 75 vk::DescriptorPoolBuilder poolBuilder; 76 77 setLayoutBuilder.addSingleBinding(vertDescType, vk::VK_SHADER_STAGE_MESH_BIT_EXT); 78 m_meshSetLayout = setLayoutBuilder.build(m_vk, device); 79 80 poolBuilder.addType(vertDescType); 81 m_descriptorPool = poolBuilder.build(m_vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 82 83 m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_meshSetLayout.get()); 84 pcRanges.push_back(vk::makePushConstantRange(vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, static_cast<uint32_t>(sizeof(uint32_t)))); 85 } 86#endif // CTS_USES_VULKANSC 87 88 std::vector<vk::VkDescriptorSetLayout> rawSetLayouts; 89 90 if (m_meshSetLayout) 91 rawSetLayouts.push_back(m_meshSetLayout.get()); 92 93 if (m_otherSetLayout) 94 rawSetLayouts.push_back(m_otherSetLayout.get()); 95 96 m_pipelineLayout = vk::PipelineLayoutWrapper(m_pipelineConstructionType, m_vk, device, de::sizeU32(rawSetLayouts), de::dataOrNull(rawSetLayouts), de::sizeU32(pcRanges), de::dataOrNull(pcRanges)); 97 98 const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 }; 99 const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, 100 vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT); 101 102 m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex()); 103 104 const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat); 105 m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo); 106 107 const vk::VkVertexInputBindingDescription vertexInputBindingDescription = 108 { 109 0, 110 (deUint32)sizeof(tcu::Vec4) * 2, 111 vk::VK_VERTEX_INPUT_RATE_VERTEX, 112 }; 113 114 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 115 { 116 { 117 0u, 118 0u, 119 vk::VK_FORMAT_R32G32B32A32_SFLOAT, 120 0u 121 }, 122 { 123 1u, 124 0u, 125 vk::VK_FORMAT_R32G32B32A32_SFLOAT, 126 (deUint32)(sizeof(float)* 4), 127 } 128 }; 129 130 m_vertexInputState = PipelineCreateInfo::VertexInputState( 131 1, 132 &vertexInputBindingDescription, 133 2, 134 vertexInputAttributeDescriptions); 135 136 const vk::VkDeviceSize dataSize = de::dataSize(m_data); 137 const vk::VkBufferUsageFlags bufferUsage = (m_isMesh ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 138 m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize, bufferUsage), 139 m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible); 140 141 deUint8* ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr()); 142 deMemcpy(ptr, &m_data[0], (size_t)dataSize); 143 144 vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory()); 145 146 // Update descriptor set for mesh shaders. 147 if (m_isMesh) 148 { 149 vk::DescriptorSetUpdateBuilder updateBuilder; 150 const auto location = vk::DescriptorSetUpdateBuilder::Location::binding(0u); 151 const auto bufferInfo = vk::makeDescriptorBufferInfo(m_vertexBuffer->object(), 0ull, dataSize); 152 153 updateBuilder.writeSingle(m_descriptorSet.get(), location, vertDescType, &bufferInfo); 154 updateBuilder.update(m_vk, device); 155 } 156 157 const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex); 158 m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo); 159 160 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 161 { 162 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 163 DE_NULL, // const void* pNext; 164 *m_cmdPool, // VkCommandPool commandPool; 165 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 166 1u, // deUint32 bufferCount; 167 }; 168 m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo); 169 170 initRenderPass(device); 171 initFramebuffer(device); 172 initPipeline(device); 173} 174 175 176void DynamicStateBaseClass::initRenderPass (const vk::VkDevice device) 177{ 178 RenderPassCreateInfo renderPassCreateInfo; 179 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat, 180 vk::VK_SAMPLE_COUNT_1_BIT, 181 vk::VK_ATTACHMENT_LOAD_OP_LOAD, 182 vk::VK_ATTACHMENT_STORE_OP_STORE, 183 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, 184 vk::VK_ATTACHMENT_STORE_OP_STORE, 185 vk::VK_IMAGE_LAYOUT_GENERAL, 186 vk::VK_IMAGE_LAYOUT_GENERAL)); 187 188 const vk::VkAttachmentReference colorAttachmentReference = 189 { 190 0, 191 vk::VK_IMAGE_LAYOUT_GENERAL 192 }; 193 194 renderPassCreateInfo.addSubpass(SubpassDescription( 195 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 196 0, 197 0, 198 DE_NULL, 199 1, 200 &colorAttachmentReference, 201 DE_NULL, 202 AttachmentReference(), 203 0, 204 DE_NULL 205 ) 206 ); 207 208 m_renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, m_vk, device, &renderPassCreateInfo); 209} 210 211void DynamicStateBaseClass::initFramebuffer (const vk::VkDevice device) 212{ 213 std::vector<vk::VkImageView> colorAttachments(1); 214 colorAttachments[0] = *m_colorTargetView; 215 216 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1); 217 218 m_renderPass.createFramebuffer(m_vk, device, &framebufferCreateInfo, m_colorTargetImage->object()); 219} 220 221void DynamicStateBaseClass::initPipeline (const vk::VkDevice device) 222{ 223 const PipelineCreateInfo::ColorBlendState colorBlendState(1, &m_attachmentState); 224 const PipelineCreateInfo::RasterizerState rasterizerState; 225 const PipelineCreateInfo::DepthStencilState depthStencilState; 226 const PipelineCreateInfo::DynamicState dynamicState; 227 const PipelineCreateInfo::MultiSampleState multisampleState; 228 229 const auto& binaries = m_context.getBinaryCollection(); 230 const vk::ShaderWrapper ms (m_isMesh ? vk::ShaderWrapper(m_vk, device, binaries.get(m_meshShaderName), 0) : vk::ShaderWrapper()); 231 const vk::ShaderWrapper vs (m_isMesh ? vk::ShaderWrapper() : vk::ShaderWrapper(m_vk, device, binaries.get(m_vertexShaderName), 0)); 232 const vk::ShaderWrapper fs (vk::ShaderWrapper(m_vk, device, binaries.get(m_fragmentShaderName), 0)); 233 std::vector<vk::VkViewport> viewports { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; 234 std::vector<vk::VkRect2D> scissors { { { 0u, 0u }, { 0u, 0u } }}; 235 236 m_pipeline.setDefaultTopology(m_topology) 237 .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState)); 238 239#ifndef CTS_USES_VULKANSC 240 if (m_isMesh) 241 { 242 m_pipeline 243 .setupPreRasterizationMeshShaderState(viewports, 244 scissors, 245 m_pipelineLayout, 246 *m_renderPass, 247 0u, 248 vk::ShaderWrapper(), 249 ms, 250 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState)); 251 } 252 else 253#endif // CTS_USES_VULKANSC 254 { 255 m_pipeline 256 .setupVertexInputState(&m_vertexInputState) 257 .setupPreRasterizationShaderState(viewports, 258 scissors, 259 m_pipelineLayout, 260 *m_renderPass, 261 0u, 262 vs, 263 static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState)); 264 } 265 266 m_pipeline.setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState), &multisampleState) 267 .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState), &multisampleState) 268 .setMonolithicPipelineLayout(m_pipelineLayout) 269 .buildPipeline(); 270} 271 272tcu::TestStatus DynamicStateBaseClass::iterate (void) 273{ 274 DE_ASSERT(false); 275 return tcu::TestStatus::fail("Implement iterate() method!"); 276} 277 278void DynamicStateBaseClass::beginRenderPass (void) 279{ 280 const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } }; 281 beginRenderPassWithClearColor(clearColor); 282} 283 284void DynamicStateBaseClass::beginRenderPassWithClearColor(const vk::VkClearColorValue& clearColor, const bool skipBeginCmdBuffer, const bool previousTransfer) 285{ 286 if (!skipBeginCmdBuffer) 287 { 288 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u); 289 } 290 291 if (previousTransfer) 292 { 293 const auto transfer2Transfer = vk::makeMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, (vk::VK_ACCESS_TRANSFER_WRITE_BIT | vk::VK_ACCESS_TRANSFER_READ_BIT)); 294 vk::cmdPipelineMemoryBarrier(m_vk, *m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &transfer2Transfer); 295 } 296 else 297 { 298 initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 299 vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT); 300 } 301 302 const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT); 303 m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(), 304 vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange); 305 306 const vk::VkMemoryBarrier memBarrier = 307 { 308 vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER, 309 DE_NULL, 310 vk::VK_ACCESS_TRANSFER_WRITE_BIT, 311 vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT 312 }; 313 314 m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 315 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 316 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL); 317 318 m_renderPass.begin(m_vk, *m_cmdBuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT)); 319} 320 321void DynamicStateBaseClass::setDynamicViewportState (const deUint32 width, const deUint32 height) 322{ 323 vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(width, height)); 324 vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(width, height)); 325 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType)) 326 { 327#ifndef CTS_USES_VULKANSC 328 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, 1, &viewport); 329 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, 1, &scissor); 330#else 331 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1, &viewport); 332 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, 1, &scissor); 333#endif 334 } 335 else 336 { 337 m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport); 338 m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor); 339 } 340} 341 342void DynamicStateBaseClass::setDynamicViewportState (deUint32 viewportCount, const vk::VkViewport* pViewports, const vk::VkRect2D* pScissors) 343{ 344 if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType)) 345 { 346#ifndef CTS_USES_VULKANSC 347 m_vk.cmdSetViewportWithCount(*m_cmdBuffer, viewportCount, pViewports); 348 m_vk.cmdSetScissorWithCount(*m_cmdBuffer, viewportCount, pScissors); 349#else 350 m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, viewportCount, pViewports); 351 m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, viewportCount, pScissors); 352#endif 353 } 354 else 355 { 356 m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports); 357 m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors); 358 } 359} 360 361void DynamicStateBaseClass::setDynamicRasterizationState (const float lineWidth, 362 const float depthBiasConstantFactor, 363 const float depthBiasClamp, 364 const float depthBiasSlopeFactor) 365{ 366 m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth); 367 m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); 368} 369 370void DynamicStateBaseClass::setDynamicBlendState (const float const1, const float const2, const float const3, const float const4) 371{ 372 float blendConstantsants[4] = { const1, const2, const3, const4 }; 373 m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants); 374} 375 376void DynamicStateBaseClass::setDynamicDepthStencilState (const float minDepthBounds, 377 const float maxDepthBounds, 378 const deUint32 stencilFrontCompareMask, 379 const deUint32 stencilFrontWriteMask, 380 const deUint32 stencilFrontReference, 381 const deUint32 stencilBackCompareMask, 382 const deUint32 stencilBackWriteMask, 383 const deUint32 stencilBackReference) 384{ 385 m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds); 386 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask); 387 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask); 388 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference); 389 m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask); 390 m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask); 391 m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference); 392} 393 394#ifndef CTS_USES_VULKANSC 395void DynamicStateBaseClass::pushVertexOffset (const uint32_t vertexOffset, 396 const vk::VkPipelineLayout pipelineLayout, 397 const vk::VkShaderStageFlags stageFlags) 398{ 399 m_vk.cmdPushConstants(*m_cmdBuffer, pipelineLayout, stageFlags, 0u, static_cast<uint32_t>(sizeof(uint32_t)), &vertexOffset); 400} 401#endif // CTS_USES_VULKANSC 402 403} // DynamicState 404} // vkt 405