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 #include "vkBarrierUtil.hpp" 41 #include "vkCmdUtil.hpp" 42 #include "vkObjUtil.hpp" 43 44 #include "tcuTestLog.hpp" 45 46 #include "deUniquePtr.hpp" 47 #include "deStringUtil.hpp" 48 49 #include <string> 50 51 namespace vkt 52 { 53 namespace FragmentOperations 54 { 55 namespace 56 { 57 using namespace vk; 58 using de::UniquePtr; 59 60 //! Basic 2D image. 61 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage) 62 { 63 const VkImageCreateInfo imageParams = 64 { 65 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 66 DE_NULL, // const void* pNext; 67 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 68 VK_IMAGE_TYPE_2D, // VkImageType imageType; 69 format, // VkFormat format; 70 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 71 1u, // deUint32 mipLevels; 72 1u, // deUint32 arrayLayers; 73 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 74 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 75 usage, // VkImageUsageFlags usage; 76 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 77 0u, // deUint32 queueFamilyIndexCount; 78 DE_NULL, // const deUint32* pQueueFamilyIndices; 79 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 80 }; 81 return imageParams; 82 } 83 84 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, 85 const VkDevice device, 86 const VkFormat colorFormat, 87 const bool useDepthStencilAttachment, 88 const VkFormat depthStencilFormat) 89 { 90 return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED); 91 } 92 93 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface& vk, 94 const VkDevice device, 95 const VkRenderPass renderPass, 96 const deUint32 attachmentCount, 97 const VkImageView* pAttachments, 98 const tcu::IVec2 size) 99 { 100 const VkFramebufferCreateInfo framebufferInfo = { 101 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 102 DE_NULL, // const void* pNext; 103 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags; 104 renderPass, // VkRenderPass renderPass; 105 attachmentCount, // uint32_t attachmentCount; 106 pAttachments, // const VkImageView* pAttachments; 107 static_cast<deUint32>(size.x()), // uint32_t width; 108 static_cast<deUint32>(size.y()), // uint32_t height; 109 1u, // uint32_t layers; 110 }; 111 112 return createFramebuffer(vk, device, &framebufferInfo); 113 } 114 115 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk, 116 const VkDevice device, 117 const VkPipelineLayout pipelineLayout, 118 const VkRenderPass renderPass, 119 const VkShaderModule vertexModule, 120 const VkShaderModule fragmentModule, 121 const tcu::IVec2& renderSize, 122 const bool enableDepthTest, 123 const bool enableStencilTest) 124 { 125 const std::vector<VkViewport> viewports (1, makeViewport(renderSize)); 126 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize)); 127 128 const VkStencilOpState stencilOpState = makeStencilOpState( 129 VK_STENCIL_OP_KEEP, // stencil fail 130 VK_STENCIL_OP_KEEP, // depth & stencil pass 131 VK_STENCIL_OP_KEEP, // depth only fail 132 VK_COMPARE_OP_EQUAL, // compare op 133 1u, // compare mask 134 1u, // write mask 135 1u); // reference 136 137 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = 138 { 139 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType 140 DE_NULL, // const void* pNext 141 0u, // VkPipelineDepthStencilStateCreateFlags flags 142 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable 143 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable 144 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp 145 VK_FALSE, // VkBool32 depthBoundsTestEnable 146 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable 147 stencilOpState, // VkStencilOpState front 148 stencilOpState, // VkStencilOpState back 149 0.0f, // float minDepthBounds 150 1.0f // float maxDepthBounds 151 }; 152 153 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk 154 device, // const VkDevice device 155 pipelineLayout, // const VkPipelineLayout pipelineLayout 156 vertexModule, // const VkShaderModule vertexShaderModule 157 DE_NULL, // const VkShaderModule tessellationControlModule 158 DE_NULL, // const VkShaderModule tessellationEvalModule 159 DE_NULL, // const VkShaderModule geometryShaderModule 160 fragmentModule, // const VkShaderModule fragmentShaderModule 161 renderPass, // const VkRenderPass renderPass 162 viewports, // const std::vector<VkViewport>& viewports 163 scissors, // const std::vector<VkRect2D>& scissors 164 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology 165 0u, // const deUint32 subpass 166 0u, // const deUint32 patchControlPoints 167 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo 168 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo 169 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo 170 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo 171 } 172 173 void commandClearStencilAttachment (const DeviceInterface& vk, 174 const VkCommandBuffer commandBuffer, 175 const VkOffset2D& offset, 176 const VkExtent2D& extent, 177 const deUint32 clearValue) 178 { 179 const VkClearAttachment stencilAttachment = 180 { 181 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask; 182 0u, // uint32_t colorAttachment; 183 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue; 184 }; 185 186 const VkClearRect rect = 187 { 188 { offset, extent }, // VkRect2D rect; 189 0u, // uint32_t baseArrayLayer; 190 1u, // uint32_t layerCount; 191 }; 192 193 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect); 194 } 195 196 VkImageAspectFlags getImageAspectFlags (const VkFormat format) 197 { 198 const tcu::TextureFormat tcuFormat = mapVkFormat(format); 199 200 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 201 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT; 202 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT; 203 204 DE_ASSERT(false); 205 return 0u; 206 } 207 208 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format) 209 { 210 VkFormatProperties formatProps; 211 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps); 212 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; 213 } 214 215 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, 216 const VkPhysicalDevice device, 217 const deUint32 numFormats, 218 const VkFormat* pFormats) 219 { 220 for (deUint32 i = 0; i < numFormats; ++i) 221 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i])) 222 return pFormats[i]; 223 return VK_FORMAT_UNDEFINED; 224 } 225 226 enum Flags 227 { 228 FLAG_TEST_DEPTH = 1u << 0, 229 FLAG_TEST_STENCIL = 1u << 1, 230 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2, 231 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3, 232 }; 233 234 class EarlyFragmentTest : public TestCase 235 { 236 public: 237 EarlyFragmentTest (tcu::TestContext& testCtx, 238 const std::string name, 239 const deUint32 flags); 240 241 void initPrograms (SourceCollections& programCollection) const; 242 TestInstance* createInstance (Context& context) const; 243 244 private: 245 const deUint32 m_flags; 246 }; 247 248 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags) 249 : TestCase (testCtx, name, "") 250 , m_flags (flags) 251 { 252 } 253 254 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const 255 { 256 // Vertex 257 { 258 std::ostringstream src; 259 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 260 << "\n" 261 << "layout(location = 0) in highp vec4 position;\n" 262 << "\n" 263 << "out gl_PerVertex {\n" 264 << " vec4 gl_Position;\n" 265 << "};\n" 266 << "\n" 267 << "void main (void)\n" 268 << "{\n" 269 << " gl_Position = position;\n" 270 << "}\n"; 271 272 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 273 } 274 275 // Fragment 276 { 277 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0; 278 std::ostringstream src; 279 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n" 280 << "\n" 281 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "") 282 << "layout(location = 0) out highp vec4 fragColor;\n" 283 << "\n" 284 << "layout(binding = 0) coherent buffer Output {\n" 285 << " uint result;\n" 286 << "} sb_out;\n" 287 << "\n" 288 << "void main (void)\n" 289 << "{\n" 290 << " atomicAdd(sb_out.result, 1u);\n" 291 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" 292 << "}\n"; 293 294 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 295 } 296 } 297 298 class EarlyFragmentTestInstance : public TestInstance 299 { 300 public: 301 EarlyFragmentTestInstance (Context& context, const deUint32 flags); 302 303 tcu::TestStatus iterate (void); 304 305 private: 306 enum TestMode 307 { 308 MODE_INVALID, 309 MODE_DEPTH, 310 MODE_STENCIL, 311 }; 312 313 const TestMode m_testMode; 314 const bool m_useTestAttachment; 315 const bool m_useEarlyTests; 316 }; 317 318 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags) 319 : TestInstance (context) 320 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH : 321 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID) 322 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0) 323 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0) 324 { 325 DE_ASSERT(m_testMode != MODE_INVALID); 326 } 327 328 tcu::TestStatus EarlyFragmentTestInstance::iterate (void) 329 { 330 const DeviceInterface& vk = m_context.getDeviceInterface(); 331 const InstanceInterface& vki = m_context.getInstanceInterface(); 332 const VkDevice device = m_context.getDevice(); 333 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); 334 const VkQueue queue = m_context.getUniversalQueue(); 335 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 336 Allocator& allocator = m_context.getDefaultAllocator(); 337 338 // Color attachment 339 340 const tcu::IVec2 renderSize = tcu::IVec2(32, 32); 341 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; 342 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 343 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))); 344 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any)); 345 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange)); 346 347 // Test attachment (depth or stencil) 348 static const VkFormat stencilFormats[] = 349 { 350 // One of the following formats must be supported, as per spec requirement. 351 VK_FORMAT_S8_UINT, 352 VK_FORMAT_D16_UNORM_S8_UINT, 353 VK_FORMAT_D24_UNORM_S8_UINT, 354 VK_FORMAT_D32_SFLOAT_S8_UINT, 355 }; 356 357 const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) 358 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported 359 if (testFormat == VK_FORMAT_UNDEFINED) 360 return tcu::TestStatus::fail("Required depth/stencil format not supported"); 361 362 if (m_useTestAttachment) 363 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage; 364 365 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u); 366 const Unique<VkImage> testImage (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))); 367 const UniquePtr<Allocation> testImageAlloc (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any)); 368 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange)); 369 const VkImageView attachmentImages[] = { *colorImageView, *testImageView }; 370 const deUint32 numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u); 371 372 // Vertex buffer 373 374 const deUint32 numVertices = 6; 375 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices; 376 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))); 377 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible)); 378 379 { 380 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr()); 381 382 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f); 383 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); 384 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f); 385 386 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f); 387 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f); 388 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f); 389 390 flushAlloc(vk, device, *vertexBufferAlloc); 391 // No barrier needed, flushed memory is automatically visible 392 } 393 394 // Result buffer 395 396 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32); 397 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))); 398 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible)); 399 400 { 401 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr()); 402 403 *pData = 0; 404 flushAlloc(vk, device, *resultBufferAlloc); 405 } 406 407 // Render result buffer (to retrieve color attachment contents) 408 409 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y(); 410 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT))); 411 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible)); 412 413 // Descriptors 414 415 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 416 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 417 .build(vk, device)); 418 419 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 420 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 421 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 422 423 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 424 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes); 425 426 DescriptorSetUpdateBuilder() 427 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo) 428 .update(vk, device); 429 430 // Pipeline 431 432 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 433 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 434 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat)); 435 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize)); 436 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout)); 437 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize, 438 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL))); 439 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 440 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 441 442 // Draw commands 443 444 { 445 const VkRect2D renderArea = { 446 makeOffset2D(0, 0), 447 makeExtent2D(renderSize.x(), renderSize.y()), 448 }; 449 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f); 450 const VkDeviceSize vertexBufferOffset = 0ull; 451 452 beginCommandBuffer(vk, *cmdBuffer); 453 454 { 455 const VkImageMemoryBarrier barriers[] = { 456 makeImageMemoryBarrier( 457 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 458 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 459 *colorImage, colorSubresourceRange), 460 makeImageMemoryBarrier( 461 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 462 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 463 *testImage, testSubresourceRange), 464 }; 465 466 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 467 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers); 468 } 469 470 // Will clear the attachments with specified depth and stencil values. 471 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u); 472 473 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 474 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 475 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 476 477 // Mask half of the attachment image with value that will pass the stencil test. 478 if (m_useTestAttachment && m_testMode == MODE_STENCIL) 479 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u); 480 481 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u); 482 endRenderPass(vk, *cmdBuffer); 483 484 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT); 485 486 endCommandBuffer(vk, *cmdBuffer); 487 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 488 } 489 490 // Log result image 491 { 492 invalidateAlloc(vk, device, *colorBufferAlloc); 493 494 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr()); 495 496 tcu::TestLog& log = m_context.getTestContext().getLog(); 497 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess); 498 } 499 500 // Verify results 501 { 502 invalidateAlloc(vk, device, *resultBufferAlloc); 503 504 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr()); 505 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment); 506 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y(); 507 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0; 508 const int expectedMin = de::max(0, expectedCounter - tolerance); 509 const int expectedMax = expectedCounter + tolerance; 510 511 tcu::TestLog& log = m_context.getTestContext().getLog(); 512 log << tcu::TestLog::Message << "Expected value" 513 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter)) 514 << tcu::TestLog::EndMessage; 515 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage; 516 517 if (expectedMin <= actualCounter && actualCounter <= expectedMax) 518 return tcu::TestStatus::pass("Success"); 519 else 520 return tcu::TestStatus::fail("Value out of range"); 521 } 522 } 523 524 TestInstance* EarlyFragmentTest::createInstance (Context& context) const 525 { 526 // Check required features 527 { 528 VkPhysicalDeviceFeatures features; 529 context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features); 530 531 // SSBO writes in fragment shader 532 if (!features.fragmentStoresAndAtomics) 533 throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics"); 534 } 535 536 return new EarlyFragmentTestInstance(context, m_flags); 537 } 538 539 } // anonymous ns 540 541 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx) 542 { 543 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases")); 544 545 static const struct 546 { 547 std::string caseName; 548 deUint32 flags; 549 } cases[] = 550 { 551 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS }, 552 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS }, 553 { "early_fragment_tests_depth", FLAG_TEST_DEPTH }, 554 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL }, 555 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT }, 556 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT }, 557 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT }, 558 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT }, 559 }; 560 561 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i) 562 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags)); 563 564 return testGroup.release(); 565 } 566 567 } // FragmentOperations 568 } // vkt 569