1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * Copyright (c) 2015 The Khronos Group Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Early fragment tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktFragmentOperationsEarlyFragmentTests.hpp" 26#include "vktFragmentOperationsMakeUtil.hpp" 27#include "vktTestCaseUtil.hpp" 28 29#include "vkDefs.hpp" 30#include "vkRef.hpp" 31#include "vkRefUtil.hpp" 32#include "vkPlatform.hpp" 33#include "vkPrograms.hpp" 34#include "vkMemUtil.hpp" 35#include "vkBuilderUtil.hpp" 36#include "vkStrUtil.hpp" 37#include "vkTypeUtil.hpp" 38#include "vkQueryUtil.hpp" 39#include "vkImageUtil.hpp" 40 41#include "tcuTestLog.hpp" 42 43#include "deUniquePtr.hpp" 44#include "deStringUtil.hpp" 45 46#include <string> 47 48namespace vkt 49{ 50namespace FragmentOperations 51{ 52namespace 53{ 54using namespace vk; 55using de::UniquePtr; 56 57//! Basic 2D image. 58inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage) 59{ 60 const VkImageCreateInfo imageParams = 61 { 62 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 63 DE_NULL, // const void* pNext; 64 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 65 VK_IMAGE_TYPE_2D, // VkImageType imageType; 66 format, // VkFormat format; 67 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 68 1u, // deUint32 mipLevels; 69 1u, // deUint32 arrayLayers; 70 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 71 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 72 usage, // VkImageUsageFlags usage; 73 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 74 0u, // deUint32 queueFamilyIndexCount; 75 DE_NULL, // const deUint32* pQueueFamilyIndices; 76 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 77 }; 78 return imageParams; 79} 80 81void beginRenderPass (const DeviceInterface& vk, 82 const VkCommandBuffer commandBuffer, 83 const VkRenderPass renderPass, 84 const VkFramebuffer framebuffer, 85 const VkRect2D& renderArea, 86 const tcu::Vec4& clearColor, 87 const float clearDepth, 88 const deUint32 clearStencil) 89{ 90 const VkClearValue clearValues[] = 91 { 92 makeClearValueColor(clearColor), // attachment 0 93 makeClearValueDepthStencil(clearDepth, clearStencil), // attachment 1 94 }; 95 96 const VkRenderPassBeginInfo renderPassBeginInfo = { 97 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 98 DE_NULL, // const void* pNext; 99 renderPass, // VkRenderPass renderPass; 100 framebuffer, // VkFramebuffer framebuffer; 101 renderArea, // VkRect2D renderArea; 102 DE_LENGTH_OF_ARRAY(clearValues), // uint32_t clearValueCount; 103 clearValues, // const VkClearValue* pClearValues; 104 }; 105 106 vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 107} 108 109Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 110 const VkDevice device, 111 const VkFormat colorFormat, 112 const bool useDepthStencilAttachment, 113 const VkFormat depthStencilFormat) 114{ 115 const VkAttachmentDescription attachments[] = 116 { 117 // color 118 { 119 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 120 colorFormat, // VkFormat format; 121 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 122 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 123 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 124 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 125 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 126 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 127 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 128 }, 129 // depth/stencil 130 { 131 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 132 depthStencilFormat, // VkFormat format; 133 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 134 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 135 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 136 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp; 137 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp; 138 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 139 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 140 } 141 }; 142 143 const VkAttachmentReference unusedAttachmentReference = 144 { 145 VK_ATTACHMENT_UNUSED, // deUint32 attachment; 146 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout layout; 147 }; 148 149 const VkAttachmentReference colorAttachmentReference = 150 { 151 0u, // deUint32 attachment; 152 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 153 }; 154 155 const VkAttachmentReference depthStencilAttachmentReference = 156 { 157 1u, // deUint32 attachment; 158 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout; 159 }; 160 161 const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference); 162 163 const VkSubpassDescription subpassDescription = 164 { 165 0u, // VkSubpassDescriptionFlags flags; 166 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 167 0u, // deUint32 inputAttachmentCount; 168 DE_NULL, // const VkAttachmentReference* pInputAttachments; 169 1u, // deUint32 colorAttachmentCount; 170 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 171 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 172 pDepthStencilAttachment, // const VkAttachmentReference* pDepthStencilAttachment; 173 0u, // deUint32 preserveAttachmentCount; 174 DE_NULL // const deUint32* pPreserveAttachments; 175 }; 176 177 const VkRenderPassCreateInfo renderPassInfo = 178 { 179 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 180 DE_NULL, // const void* pNext; 181 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 182 (useDepthStencilAttachment ? 2u : 1u), // deUint32 attachmentCount; 183 attachments, // const VkAttachmentDescription* pAttachments; 184 1u, // deUint32 subpassCount; 185 &subpassDescription, // const VkSubpassDescription* pSubpasses; 186 0u, // deUint32 dependencyCount; 187 DE_NULL // const VkSubpassDependency* pDependencies; 188 }; 189 190 return createRenderPass(vk, device, &renderPassInfo); 191} 192 193Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, 194 const VkDevice device, 195 const VkRenderPass renderPass, 196 const deUint32 attachmentCount, 197 const VkImageView* pAttachments, 198 const tcu::IVec2 size) 199{ 200 const VkFramebufferCreateInfo framebufferInfo = { 201 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 202 DE_NULL, // const void* pNext; 203 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 204 renderPass, // VkRenderPass renderPass; 205 attachmentCount, // uint32_t attachmentCount; 206 pAttachments, // const VkImageView* pAttachments; 207 static_cast<deUint32>(size.x()), // uint32_t width; 208 static_cast<deUint32>(size.y()), // uint32_t height; 209 1u, // uint32_t layers; 210 }; 211 212 return createFramebuffer(vk, device, &framebufferInfo); 213} 214 215Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 216 const VkDevice device, 217 const VkPipelineLayout pipelineLayout, 218 const VkRenderPass renderPass, 219 const VkShaderModule vertexModule, 220 const VkShaderModule fragmentModule, 221 const tcu::IVec2& renderSize, 222 const bool enableDepthTest, 223 const bool enableStencilTest) 224{ 225 const VkVertexInputBindingDescription vertexInputBindingDescription = 226 { 227 0u, // uint32_t binding; 228 sizeof(tcu::Vec4), // uint32_t stride; // Vertex is a 4-element vector XYZW, position only 229 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 230 }; 231 232 const VkVertexInputAttributeDescription vertexInputAttributeDescription = 233 { 234 0u, // uint32_t location; 235 0u, // uint32_t binding; 236 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 237 0u, // uint32_t offset; 238 }; 239 240 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 241 { 242 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 243 DE_NULL, // const void* pNext; 244 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 245 1u, // uint32_t vertexBindingDescriptionCount; 246 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 247 1u, // uint32_t vertexAttributeDescriptionCount; 248 &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 249 }; 250 251 const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = 252 { 253 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 254 DE_NULL, // const void* pNext; 255 (VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags; 256 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 257 VK_FALSE, // VkBool32 primitiveRestartEnable; 258 }; 259 260 const VkViewport viewport = makeViewport( 261 0.0f, 0.0f, 262 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()), 263 0.0f, 1.0f); 264 265 const VkRect2D scissor = { 266 makeOffset2D(0, 0), 267 makeExtent2D(renderSize.x(), renderSize.y()), 268 }; 269 270 const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = 271 { 272 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 273 DE_NULL, // const void* pNext; 274 (VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags; 275 1u, // uint32_t viewportCount; 276 &viewport, // const VkViewport* pViewports; 277 1u, // uint32_t scissorCount; 278 &scissor, // const VkRect2D* pScissors; 279 }; 280 281 const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = 282 { 283 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 284 DE_NULL, // const void* pNext; 285 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags; 286 VK_FALSE, // VkBool32 depthClampEnable; 287 VK_FALSE, // VkBool32 rasterizerDiscardEnable; 288 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 289 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 290 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 291 VK_FALSE, // VkBool32 depthBiasEnable; 292 0.0f, // float depthBiasConstantFactor; 293 0.0f, // float depthBiasClamp; 294 0.0f, // float depthBiasSlopeFactor; 295 1.0f, // float lineWidth; 296 }; 297 298 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 299 { 300 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 301 DE_NULL, // const void* pNext; 302 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 303 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 304 VK_FALSE, // VkBool32 sampleShadingEnable; 305 0.0f, // float minSampleShading; 306 DE_NULL, // const VkSampleMask* pSampleMask; 307 VK_FALSE, // VkBool32 alphaToCoverageEnable; 308 VK_FALSE // VkBool32 alphaToOneEnable; 309 }; 310 311 const VkStencilOpState stencilOpState = makeStencilOpState( 312 VK_STENCIL_OP_KEEP, // stencil fail 313 VK_STENCIL_OP_KEEP, // depth & stencil pass 314 VK_STENCIL_OP_KEEP, // depth only fail 315 VK_COMPARE_OP_EQUAL, // compare op 316 1u, // compare mask 317 1u, // write mask 318 1u); // reference 319 320 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 321 { 322 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 323 DE_NULL, // const void* pNext; 324 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 325 enableDepthTest, // VkBool32 depthTestEnable; 326 VK_TRUE, // VkBool32 depthWriteEnable; 327 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 328 VK_FALSE, // VkBool32 depthBoundsTestEnable; 329 enableStencilTest, // VkBool32 stencilTestEnable; 330 stencilOpState, // VkStencilOpState front; 331 stencilOpState, // VkStencilOpState back; 332 0.0f, // float minDepthBounds; 333 1.0f, // float maxDepthBounds; 334 }; 335 336 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 337 // Number of blend attachments must equal the number of color attachments. 338 const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState = 339 { 340 VK_FALSE, // VkBool32 blendEnable; 341 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 342 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 343 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 344 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 345 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 346 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 347 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 348 }; 349 350 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 351 { 352 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 353 DE_NULL, // const void* pNext; 354 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 355 VK_FALSE, // VkBool32 logicOpEnable; 356 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 357 1u, // deUint32 attachmentCount; 358 &pipelineColorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 359 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 360 }; 361 362 const VkPipelineShaderStageCreateInfo pShaderStages[] = 363 { 364 { 365 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 366 DE_NULL, // const void* pNext; 367 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 368 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 369 vertexModule, // VkShaderModule module; 370 "main", // const char* pName; 371 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 372 }, 373 { 374 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 375 DE_NULL, // const void* pNext; 376 (VkPipelineShaderStageCreateFlags)0, // VkPipelineShaderStageCreateFlags flags; 377 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 378 fragmentModule, // VkShaderModule module; 379 "main", // const char* pName; 380 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 381 } 382 }; 383 384 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = 385 { 386 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 387 DE_NULL, // const void* pNext; 388 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags; 389 DE_LENGTH_OF_ARRAY(pShaderStages), // deUint32 stageCount; 390 pShaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 391 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 392 &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 393 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 394 &pipelineViewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState; 395 &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 396 &pipelineMultisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 397 &pipelineDepthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 398 &pipelineColorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 399 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 400 pipelineLayout, // VkPipelineLayout layout; 401 renderPass, // VkRenderPass renderPass; 402 0u, // deUint32 subpass; 403 DE_NULL, // VkPipeline basePipelineHandle; 404 0, // deInt32 basePipelineIndex; 405 }; 406 407 return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo); 408} 409 410VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize) 411{ 412 const VkBufferImageCopy copyParams = 413 { 414 0ull, // VkDeviceSize bufferOffset; 415 0u, // deUint32 bufferRowLength; 416 0u, // deUint32 bufferImageHeight; 417 makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 418 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 419 makeExtent3D(renderSize.x(), renderSize.y(), 1u), // VkExtent3D imageExtent; 420 }; 421 return copyParams; 422} 423 424void commandClearStencilAttachment (const DeviceInterface& vk, 425 const VkCommandBuffer commandBuffer, 426 const VkOffset2D& offset, 427 const VkExtent2D& extent, 428 const deUint32 clearValue) 429{ 430 const VkClearAttachment stencilAttachment = 431 { 432 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask; 433 0u, // uint32_t colorAttachment; 434 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue; 435 }; 436 437 const VkClearRect rect = 438 { 439 { offset, extent }, // VkRect2D rect; 440 0u, // uint32_t baseArrayLayer; 441 1u, // uint32_t layerCount; 442 }; 443 444 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect); 445} 446 447VkImageAspectFlags getImageAspectFlags (const VkFormat format) 448{ 449 const tcu::TextureFormat tcuFormat = mapVkFormat(format); 450 451 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 452 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT; 453 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT; 454 455 DE_ASSERT(false); 456 return 0u; 457} 458 459bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format) 460{ 461 VkFormatProperties formatProps; 462 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps); 463 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; 464} 465 466VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, 467 const VkPhysicalDevice device, 468 const deUint32 numFormats, 469 const VkFormat* pFormats) 470{ 471 for (deUint32 i = 0; i < numFormats; ++i) 472 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i])) 473 return pFormats[i]; 474 return VK_FORMAT_UNDEFINED; 475} 476 477enum Flags 478{ 479 FLAG_TEST_DEPTH = 1u << 0, 480 FLAG_TEST_STENCIL = 1u << 1, 481 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2, 482 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3, 483}; 484 485class EarlyFragmentTest : public TestCase 486{ 487public: 488 EarlyFragmentTest (tcu::TestContext& testCtx, 489 const std::string name, 490 const deUint32 flags); 491 492 void initPrograms (SourceCollections& programCollection) const; 493 TestInstance* createInstance (Context& context) const; 494 495private: 496 const deUint32 m_flags; 497}; 498 499EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags) 500 : TestCase (testCtx, name, "") 501 , m_flags (flags) 502{ 503} 504 505void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const 506{ 507 // Vertex 508 { 509 std::ostringstream src; 510 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 511 << "\n" 512 << "layout(location = 0) in highp vec4 position;\n" 513 << "\n" 514 << "out gl_PerVertex {\n" 515 << " vec4 gl_Position;\n" 516 << "};\n" 517 << "\n" 518 << "void main (void)\n" 519 << "{\n" 520 << " gl_Position = position;\n" 521 << "}\n"; 522 523 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 524 } 525 526 // Fragment 527 { 528 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0; 529 std::ostringstream src; 530 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 531 << "\n" 532 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "") 533 << "layout(location = 0) out highp vec4 fragColor;\n" 534 << "\n" 535 << "layout(binding = 0) coherent buffer Output {\n" 536 << " uint result;\n" 537 << "} sb_out;\n" 538 << "\n" 539 << "void main (void)\n" 540 << "{\n" 541 << " atomicAdd(sb_out.result, 1u);\n" 542 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" 543 << "}\n"; 544 545 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 546 } 547} 548 549class EarlyFragmentTestInstance : public TestInstance 550{ 551public: 552 EarlyFragmentTestInstance (Context& context, const deUint32 flags); 553 554 tcu::TestStatus iterate (void); 555 556private: 557 enum TestMode 558 { 559 MODE_INVALID, 560 MODE_DEPTH, 561 MODE_STENCIL, 562 }; 563 564 const TestMode m_testMode; 565 const bool m_useTestAttachment; 566 const bool m_useEarlyTests; 567}; 568 569EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags) 570 : TestInstance (context) 571 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH : 572 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID) 573 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0) 574 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0) 575{ 576 DE_ASSERT(m_testMode != MODE_INVALID); 577} 578 579tcu::TestStatus EarlyFragmentTestInstance::iterate (void) 580{ 581 const DeviceInterface& vk = m_context.getDeviceInterface(); 582 const InstanceInterface& vki = m_context.getInstanceInterface(); 583 const VkDevice device = m_context.getDevice(); 584 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); 585 const VkQueue queue = m_context.getUniversalQueue(); 586 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 587 Allocator& allocator = m_context.getDefaultAllocator(); 588 589 // Color attachment 590 591 const tcu::IVec2 renderSize = tcu::IVec2(32, 32); 592 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 593 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 594 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); 595 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any)); 596 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)); 597 598 // Test attachment (depth or stencil) 599 static const VkFormat stencilFormats[] = 600 { 601 // One of the following formats must be supported, as per spec requirement. 602 VK_FORMAT_S8_UINT, 603 VK_FORMAT_D16_UNORM_S8_UINT, 604 VK_FORMAT_D24_UNORM_S8_UINT, 605 VK_FORMAT_D32_SFLOAT_S8_UINT, 606 }; 607 608 const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) 609 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported 610 if (testFormat == VK_FORMAT_UNDEFINED) 611 return tcu::TestStatus::fail("Required depth/stencil format not supported"); 612 613 if (m_useTestAttachment) 614 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage; 615 616 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u); 617 const Unique<VkImage> testImage (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))); 618 const UniquePtr<Allocation> testImageAlloc (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any)); 619 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange)); 620 const VkImageView attachmentImages[] = { *colorImageView, *testImageView }; 621 const deUint32 numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u); 622 623 // Vertex buffer 624 625 const deUint32 numVertices = 6; 626 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices; 627 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))); 628 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 629 630 { 631 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr()); 632 633 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f); 634 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); 635 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f); 636 637 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f); 638 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f); 639 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f); 640 641 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSizeBytes); 642 // No barrier needed, flushed memory is automatically visible 643 } 644 645 // Result buffer 646 647 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32); 648 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))); 649 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible)); 650 651 { 652 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr()); 653 654 *pData = 0; 655 flushMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes); 656 } 657 658 // Render result buffer (to retrieve color attachment contents) 659 660 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y(); 661 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); 662 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 663 664 // Descriptors 665 666 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 667 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 668 .build(vk, device)); 669 670 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 671 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 672 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 673 674 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 675 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes); 676 677 DescriptorSetUpdateBuilder() 678 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo) 679 .update(vk, device); 680 681 // Pipeline 682 683 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 684 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 685 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat)); 686 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize)); 687 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout)); 688 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize, 689 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL))); 690 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 691 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 692 693 // Draw commands 694 695 { 696 const VkRect2D renderArea = { 697 makeOffset2D(0, 0), 698 makeExtent2D(renderSize.x(), renderSize.y()), 699 }; 700 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f); 701 const VkDeviceSize vertexBufferOffset = 0ull; 702 703 beginCommandBuffer(vk, *cmdBuffer); 704 705 { 706 const VkImageMemoryBarrier barriers[] = { 707 makeImageMemoryBarrier( 708 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 709 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 710 *colorImage, colorSubresourceRange), 711 makeImageMemoryBarrier( 712 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 713 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 714 *testImage, testSubresourceRange), 715 }; 716 717 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 718 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 719 } 720 721 // Will clear the attachments with specified depth and stencil values. 722 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u); 723 724 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 725 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 726 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 727 728 // Mask half of the attachment image with value that will pass the stencil test. 729 if (m_useTestAttachment && m_testMode == MODE_STENCIL) 730 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u); 731 732 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u); 733 vk.cmdEndRenderPass(*cmdBuffer); 734 735 { 736 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier( 737 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes); 738 739 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 740 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL); 741 742 const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier( 743 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, 744 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 745 *colorImage, colorSubresourceRange); 746 747 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 748 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier); 749 750 const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize); 751 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, ©Region); 752 753 const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier( 754 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes); 755 756 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 757 0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL); 758 } 759 760 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 761 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 762 } 763 764 // Log result image 765 { 766 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSizeBytes); 767 768 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr()); 769 770 tcu::TestLog& log = m_context.getTestContext().getLog(); 771 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess); 772 } 773 774 // Verify results 775 { 776 invalidateMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes); 777 778 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr()); 779 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment); 780 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y(); 781 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0; 782 const int expectedMin = de::max(0, expectedCounter - tolerance); 783 const int expectedMax = expectedCounter + tolerance; 784 785 tcu::TestLog& log = m_context.getTestContext().getLog(); 786 log << tcu::TestLog::Message << "Expected value" 787 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter)) 788 << tcu::TestLog::EndMessage; 789 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage; 790 791 if (expectedMin <= actualCounter && actualCounter <= expectedMax) 792 return tcu::TestStatus::pass("Success"); 793 else 794 return tcu::TestStatus::fail("Value out of range"); 795 } 796} 797 798TestInstance* EarlyFragmentTest::createInstance (Context& context) const 799{ 800 // Check required features 801 { 802 VkPhysicalDeviceFeatures features; 803 context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features); 804 805 // SSBO writes in fragment shader 806 if (!features.fragmentStoresAndAtomics) 807 throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics"); 808 } 809 810 return new EarlyFragmentTestInstance(context, m_flags); 811} 812 813} // anonymous ns 814 815tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx) 816{ 817 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases")); 818 819 static const struct 820 { 821 std::string caseName; 822 deUint32 flags; 823 } cases[] = 824 { 825 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS }, 826 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS }, 827 { "early_fragment_tests_depth", FLAG_TEST_DEPTH }, 828 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL }, 829 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT }, 830 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT }, 831 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT }, 832 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT }, 833 }; 834 835 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) 836 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags)); 837 838 return testGroup.release(); 839} 840 841} // FragmentOperations 842} // vkt 843