1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 Advanced Micro Devices, Inc. 6 * Copyright (c) 2017 The Khronos Group Inc. 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 Tests for VK_EXT_sample_locations 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineMultisampleSampleLocationsExtTests.hpp" 28#include "vktPipelineSampleLocationsUtil.hpp" 29#include "vktPipelineMakeUtil.hpp" 30#include "vktTestCase.hpp" 31#include "vktTestGroupUtil.hpp" 32#include "vktTestCaseUtil.hpp" 33 34#include "vkPlatform.hpp" 35#include "vkMemUtil.hpp" 36#include "vkQueryUtil.hpp" 37#include "vkTypeUtil.hpp" 38#include "vkRefUtil.hpp" 39#include "vkBuilderUtil.hpp" 40#include "vkPrograms.hpp" 41#include "vkImageUtil.hpp" 42#include "vkCmdUtil.hpp" 43#include "vkObjUtil.hpp" 44 45#include "deUniquePtr.hpp" 46#include "deRandom.hpp" 47#include "deMath.h" 48 49#include "tcuTestLog.hpp" 50#include "tcuImageCompare.hpp" 51#include "tcuTextureUtil.hpp" 52#include "tcuRGBA.hpp" 53#include "tcuVectorUtil.hpp" 54 55#include <string> 56#include <vector> 57#include <set> 58#include <algorithm> 59 60namespace vkt 61{ 62namespace pipeline 63{ 64namespace 65{ 66using namespace vk; 67using de::UniquePtr; 68using de::MovePtr; 69using tcu::Vec4; 70using tcu::Vec2; 71using tcu::UVec2; 72using tcu::UVec4; 73using tcu::RGBA; 74 75static const deUint32 STENCIL_REFERENCE = 1u; 76static const float DEPTH_CLEAR = 1.0f; 77static const float DEPTH_REFERENCE = 0.5f; 78static const Vec4 CLEAR_COLOR_0 = Vec4(0.0f, 0.0f, 0.0f, 1.0f); 79static const Vec4 CLEAR_COLOR_1 = Vec4(0.5f, 0.25f, 0.75f, 1.0f); 80static const VkDeviceSize ZERO = 0u; 81 82template<typename T> 83inline const T* dataOrNullPtr (const std::vector<T>& v) 84{ 85 return (v.empty() ? DE_NULL : &v[0]); 86} 87 88template<typename T> 89inline T* dataOrNullPtr (std::vector<T>& v) 90{ 91 return (v.empty() ? DE_NULL : &v[0]); 92} 93 94template<typename T> 95inline void append (std::vector<T>& first, const std::vector<T>& second) 96{ 97 first.insert(first.end(), second.begin(), second.end()); 98} 99 100//! Order a Vector by X, Y, Z, and W 101template<typename VectorT> 102struct LessThan 103{ 104 bool operator()(const VectorT& v1, const VectorT& v2) const 105 { 106 for (int i = 0; i < VectorT::SIZE; ++i) 107 { 108 if (v1[i] == v2[i]) 109 continue; 110 else 111 return v1[i] < v2[i]; 112 } 113 114 return false; 115 } 116}; 117 118//! Similar to the class in vktTestCaseUtil.hpp, but uses Arg0 directly rather than through a InstanceFunction1 119template<typename Arg0> 120class FunctionProgramsSimple1 121{ 122public: 123 typedef void (*Function) (vk::SourceCollections& dst, Arg0 arg0); 124 FunctionProgramsSimple1 (Function func) : m_func(func) {} 125 void init (vk::SourceCollections& dst, const Arg0& arg0) const { m_func(dst, arg0); } 126 127private: 128 const Function m_func; 129}; 130 131//! Convenience function to create a TestCase based on a freestanding initPrograms and a TestInstance implementation 132template<typename Instance, typename Arg0> 133void addInstanceTestCaseWithPrograms (tcu::TestCaseGroup* group, 134 const std::string& name, 135 typename FunctionSupport1<Arg0>::Function checkSupport, 136 typename FunctionProgramsSimple1<Arg0>::Function initPrograms, 137 Arg0 arg0) 138{ 139 group->addChild(new InstanceFactory1WithSupport<Instance, Arg0, FunctionSupport1<Arg0>, FunctionProgramsSimple1<Arg0> >( 140 group->getTestContext(), tcu::NODETYPE_SELF_VALIDATE, name, FunctionProgramsSimple1<Arg0>(initPrograms), arg0, typename FunctionSupport1<Arg0>::Args(checkSupport, arg0))); 141} 142 143void checkSupportSampleLocations (Context& context) 144{ 145 context.requireDeviceFunctionality("VK_EXT_sample_locations"); 146} 147 148std::string getString (const VkSampleCountFlagBits sampleCount) 149{ 150 std::ostringstream str; 151 str << "samples_" << static_cast<deUint32>(sampleCount); 152 return str.str(); 153} 154 155bool isSupportedDepthStencilFormat (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat format) 156{ 157 VkFormatProperties formatProps; 158 vki.getPhysicalDeviceFormatProperties(physDevice, format, &formatProps); 159 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0; 160} 161 162VkFormat findSupportedDepthStencilFormat (Context& context, const bool useDepth, const bool useStencil) 163{ 164 const InstanceInterface& vki = context.getInstanceInterface(); 165 const VkPhysicalDevice physDevice = context.getPhysicalDevice(); 166 167 if (useDepth && !useStencil) 168 return VK_FORMAT_D16_UNORM; // must be supported 169 170 // One of these formats must be supported. 171 172 if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D24_UNORM_S8_UINT)) 173 return VK_FORMAT_D24_UNORM_S8_UINT; 174 175 if (isSupportedDepthStencilFormat(vki, physDevice, VK_FORMAT_D32_SFLOAT_S8_UINT)) 176 return VK_FORMAT_D32_SFLOAT_S8_UINT; 177 178 return VK_FORMAT_UNDEFINED; 179} 180 181void checkFragmentShadingRateRequirements(Context& context, deUint32 sampleCount) 182{ 183 const auto& vki = context.getInstanceInterface(); 184 const auto physicalDevice = context.getPhysicalDevice(); 185 186 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate"); 187 188 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate) 189 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported"); 190 191 // Fetch information about supported fragment shading rates 192 deUint32 supportedFragmentShadingRateCount = 0; 193 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL); 194 195 std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(supportedFragmentShadingRateCount, 196 { 197 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, 198 DE_NULL, 199 vk::VK_SAMPLE_COUNT_1_BIT, 200 {1, 1} 201 }); 202 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, supportedFragmentShadingRates.data()); 203 204 bool requiredRateFound = false; 205 for (const auto& rate : supportedFragmentShadingRates) 206 { 207 if ((rate.fragmentSize.width == 2u) && 208 (rate.fragmentSize.height == 2u) && 209 (rate.sampleCounts & sampleCount)) 210 { 211 requiredRateFound = true; 212 break; 213 } 214 } 215 216 if (!requiredRateFound) 217 TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported"); 218} 219 220VkImageAspectFlags getImageAspectFlags (const VkFormat format) 221{ 222 const tcu::TextureFormat tcuFormat = mapVkFormat(format); 223 224 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 225 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT; 226 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT; 227 228 DE_FATAL("Format not handled"); 229 return 0u; 230} 231 232VkPhysicalDeviceSampleLocationsPropertiesEXT getSampleLocationsPropertiesEXT (Context& context) 233{ 234 const InstanceInterface& vki = context.getInstanceInterface(); 235 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 236 237 VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties; 238 deMemset(&sampleLocationsProperties, 0, sizeof(sampleLocationsProperties)); 239 240 sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT; 241 sampleLocationsProperties.pNext = DE_NULL; 242 243 VkPhysicalDeviceProperties2 properties = 244 { 245 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType; 246 &sampleLocationsProperties, // void* pNext; 247 VkPhysicalDeviceProperties(), // VkPhysicalDeviceProperties properties; 248 }; 249 250 vki.getPhysicalDeviceProperties2(physicalDevice, &properties); 251 252 return sampleLocationsProperties; 253} 254 255inline deUint32 numSamplesPerPixel (const MultisamplePixelGrid& pixelGrid) 256{ 257 return static_cast<deUint32>(pixelGrid.samplesPerPixel()); 258} 259 260inline VkSampleLocationsInfoEXT makeEmptySampleLocationsInfo () 261{ 262 const VkSampleLocationsInfoEXT info = 263 { 264 VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, // VkStructureType sType; 265 DE_NULL, // const void* pNext; 266 (VkSampleCountFlagBits)0, // VkSampleCountFlagBits sampleLocationsPerPixel; 267 makeExtent2D(0,0), // VkExtent2D sampleLocationGridSize; 268 0, // uint32_t sampleLocationsCount; 269 DE_NULL, // const VkSampleLocationEXT* pSampleLocations; 270 }; 271 return info; 272} 273 274void logPixelGrid (tcu::TestLog& log, const VkPhysicalDeviceSampleLocationsPropertiesEXT& sampleLocationsProperties, const MultisamplePixelGrid& pixelGrid) 275{ 276 log << tcu::TestLog::Section("pixelGrid", "Multisample pixel grid configuration:") 277 << tcu::TestLog::Message << sampleLocationsProperties << tcu::TestLog::EndMessage 278 << tcu::TestLog::Message << "Specified grid size = " << pixelGrid.size() << tcu::TestLog::EndMessage; 279 280 for (deUint32 gridY = 0; gridY < pixelGrid.size().y(); ++gridY) 281 for (deUint32 gridX = 0; gridX < pixelGrid.size().x(); ++gridX) 282 { 283 log << tcu::TestLog::Message << "Pixel(" << gridX << ", " << gridY <<")" << tcu::TestLog::EndMessage; 284 285 for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(pixelGrid); ++sampleNdx) 286 { 287 const VkSampleLocationEXT& loc = pixelGrid.getSample(gridX, gridY, sampleNdx); 288 log << tcu::TestLog::Message << "* Sample(" << sampleNdx <<") = " << Vec2(loc.x, loc.y) << tcu::TestLog::EndMessage; 289 } 290 } 291 292 log << tcu::TestLog::Message << "Sample locations visualization" << tcu::TestLog::EndMessage; 293 294 { 295 const deUint32 height = deMinu32(1u << sampleLocationsProperties.sampleLocationSubPixelBits, 16u); // increase if you want more precision 296 const deUint32 width = 2 * height; // works well with a fixed-size font 297 std::vector<char> buffer (width * height); 298 299 for (deUint32 gridY = 0; gridY < pixelGrid.size().y(); ++gridY) 300 for (deUint32 gridX = 0; gridX < pixelGrid.size().x(); ++gridX) 301 { 302 std::fill(buffer.begin(), buffer.end(), '.'); 303 304 for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(pixelGrid); ++sampleNdx) 305 { 306 const VkSampleLocationEXT& loc = pixelGrid.getSample(gridX, gridY, sampleNdx); 307 const deUint32 ndx = deMinu32(width - 1, static_cast<deUint32>(static_cast<float>(width) * loc.x)) + 308 deMinu32(height - 1, static_cast<deUint32>(static_cast<float>(height) * loc.y)) * width; 309 const deUint32 evenNdx = ndx - ndx % 2; 310 311 buffer[evenNdx ] = '['; 312 buffer[evenNdx + 1] = ']'; 313 } 314 315 std::ostringstream str; 316 str << "Pixel(" << gridX << ", " << gridY <<")\n"; 317 318 for (deUint32 lineNdx = 0; lineNdx < height; ++lineNdx) 319 { 320 str.write(&buffer[width * lineNdx], width); 321 str << "\n"; 322 } 323 324 log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage; 325 } 326 } 327 328 log << tcu::TestLog::EndSection; 329} 330 331//! Place samples very close to each other 332void fillSampleLocationsPacked (MultisamplePixelGrid& grid, const deUint32 subPixelBits) 333{ 334 const deUint32 numLocations = 1u << subPixelBits; 335 const int offset[3] = { -1, 0, 1 }; 336 de::Random rng (214); 337 338 for (deUint32 gridY = 0; gridY < grid.size().y(); ++gridY) 339 for (deUint32 gridX = 0; gridX < grid.size().x(); ++gridX) 340 { 341 // Will start placing from this location 342 const UVec2 baseLocationNdx (rng.getUint32() % numLocations, 343 rng.getUint32() % numLocations); 344 UVec2 locationNdx = baseLocationNdx; 345 346 std::set<UVec2, LessThan<UVec2> > takenLocationIndices; 347 for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(grid); /* no increment */) 348 { 349 if (takenLocationIndices.find(locationNdx) == takenLocationIndices.end()) 350 { 351 const VkSampleLocationEXT location = 352 { 353 static_cast<float>(locationNdx.x()) / static_cast<float>(numLocations), // float x; 354 static_cast<float>(locationNdx.y()) / static_cast<float>(numLocations), // float y; 355 }; 356 357 grid.setSample(gridX, gridY, sampleNdx, location); 358 takenLocationIndices.insert(locationNdx); 359 360 ++sampleNdx; // next sample 361 } 362 363 // Find next location by applying a small offset. Just keep iterating if a redundant location is chosen 364 locationNdx.x() = static_cast<deUint32>(deClamp32(locationNdx.x() + offset[rng.getUint32() % DE_LENGTH_OF_ARRAY(offset)], 0u, numLocations - 1)); 365 locationNdx.y() = static_cast<deUint32>(deClamp32(locationNdx.y() + offset[rng.getUint32() % DE_LENGTH_OF_ARRAY(offset)], 0u, numLocations - 1)); 366 } 367 } 368} 369 370//! Unorm/int compare, very low threshold as we are expecting near-exact values 371bool compareGreenImage (tcu::TestLog& log, const char* name, const char* description, const tcu::ConstPixelBufferAccess& image) 372{ 373 tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight()); 374 tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec()); 375 return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u), tcu::COMPARE_LOG_RESULT); 376} 377 378//! Silent compare - no logging 379bool intThresholdCompare (const tcu::ConstPixelBufferAccess& reference, const tcu::ConstPixelBufferAccess& result, const UVec4& threshold) 380{ 381 using namespace tcu; 382 383 int width = reference.getWidth(); 384 int height = reference.getHeight(); 385 int depth = reference.getDepth(); 386 UVec4 maxDiff (0, 0, 0, 0); 387 388 TCU_CHECK_INTERNAL(result.getWidth() == width && result.getHeight() == height && result.getDepth() == depth); 389 390 for (int z = 0; z < depth; z++) 391 { 392 for (int y = 0; y < height; y++) 393 { 394 for (int x = 0; x < width; x++) 395 { 396 IVec4 refPix = reference.getPixelInt(x, y, z); 397 IVec4 cmpPix = result.getPixelInt(x, y, z); 398 UVec4 diff = abs(refPix - cmpPix).cast<deUint32>(); 399 400 maxDiff = max(maxDiff, diff); 401 } 402 } 403 } 404 405 return boolAll(lessThanEqual(maxDiff, threshold)); 406} 407 408int countUniqueColors (const tcu::ConstPixelBufferAccess& image) 409{ 410 std::set<Vec4, LessThan<Vec4> > colors; 411 412 for (int y = 0; y < image.getHeight(); ++y) 413 for (int x = 0; x < image.getWidth(); ++x) 414 { 415 colors.insert(image.getPixel(x, y)); 416 } 417 418 return static_cast<int>(colors.size()); 419} 420 421Move<VkImage> makeImage (const DeviceInterface& vk, 422 const VkDevice device, 423 const VkImageCreateFlags flags, 424 const VkFormat format, 425 const UVec2& size, 426 const VkSampleCountFlagBits samples, 427 const VkImageUsageFlags usage) 428{ 429 const VkImageCreateInfo imageParams = 430 { 431 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 432 DE_NULL, // const void* pNext; 433 flags, // VkImageCreateFlags flags; 434 VK_IMAGE_TYPE_2D, // VkImageType imageType; 435 format, // VkFormat format; 436 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 437 1u, // deUint32 mipLevels; 438 1u, // deUint32 arrayLayers; 439 samples, // VkSampleCountFlagBits samples; 440 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 441 usage, // VkImageUsageFlags usage; 442 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 443 0u, // deUint32 queueFamilyIndexCount; 444 DE_NULL, // const deUint32* pQueueFamilyIndices; 445 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 446 }; 447 return createImage(vk, device, &imageParams); 448} 449 450Move<VkEvent> makeEvent (const DeviceInterface& vk, const VkDevice device) 451{ 452 const VkEventCreateInfo createInfo = 453 { 454 VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, // VkStructureType sType; 455 DE_NULL, // const void* pNext; 456 (VkEventCreateFlags)0, // VkEventCreateFlags flags; 457 }; 458 return createEvent(vk, device, &createInfo); 459} 460 461//! Generate NDC space sample locations at each framebuffer pixel 462//! Data is filled starting at pixel (0,0) and for each pixel there are numSamples locations 463std::vector<Vec2> genFramebufferSampleLocations (const MultisamplePixelGrid& pixelGrid, const UVec2& gridSize, const UVec2& framebufferSize) 464{ 465 std::vector<Vec2> locations; 466 467 for (deUint32 y = 0; y < framebufferSize.y(); ++y) 468 for (deUint32 x = 0; x < framebufferSize.x(); ++x) 469 for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel(pixelGrid); ++sampleNdx) 470 { 471 const VkSampleLocationEXT& location = pixelGrid.getSample(x % gridSize.x(), y % gridSize.y(), sampleNdx); 472 const float globalX = location.x + static_cast<float>(x); 473 const float globalY = location.y + static_cast<float>(y); 474 475 // Transform to [-1, 1] space 476 locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())), 477 -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y())))); 478 } 479 480 return locations; 481} 482 483struct PositionColor 484{ 485 tcu::Vec4 position; 486 tcu::Vec4 color; 487 488 PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos), color(col) {} 489}; 490 491std::vector<PositionColor> genVerticesFullQuad (const Vec4& color = Vec4(1.0f), const float z = 0.0f) 492{ 493 const PositionColor vertices[] = 494 { 495 PositionColor(Vec4( 1.0f, -1.0f, z, 1.0f), color), 496 PositionColor(Vec4(-1.0f, -1.0f, z, 1.0f), color), 497 PositionColor(Vec4(-1.0f, 1.0f, z, 1.0f), color), 498 499 PositionColor(Vec4(-1.0f, 1.0f, z, 1.0f), color), 500 PositionColor(Vec4( 1.0f, 1.0f, z, 1.0f), color), 501 PositionColor(Vec4( 1.0f, -1.0f, z, 1.0f), color), 502 }; 503 504 return std::vector<PositionColor>(vertices, vertices + DE_LENGTH_OF_ARRAY(vertices)); 505} 506 507//! Some abstract geometry with angled edges, to make multisampling visible. 508std::vector<PositionColor> genVerticesShapes (const Vec4& color = Vec4(1.0f), const float z = 0.0f) 509{ 510 std::vector<PositionColor> vertices; 511 512 const float numSteps = 16.0f; 513 const float angleStep = (2.0f * DE_PI) / numSteps; 514 515 for (float a = 0.0f; a <= 2.0f * DE_PI; a += angleStep) 516 { 517 vertices.push_back(PositionColor(Vec4(1.0f * deFloatCos(a), 1.0f * deFloatSin(a), z, 1.0f), color)); 518 vertices.push_back(PositionColor(Vec4(0.1f * deFloatCos(a - angleStep), 0.1f * deFloatSin(a - angleStep), z, 1.0f), color)); 519 vertices.push_back(PositionColor(Vec4(0.1f * deFloatCos(a + angleStep), 0.1f * deFloatSin(a + angleStep), z, 1.0f), color)); 520 } 521 522 return vertices; 523} 524 525//! Stencil op that only allows drawing over the cleared area of an attachment. 526inline VkStencilOpState stencilOpStateDrawOnce (void) 527{ 528 return makeStencilOpState( 529 VK_STENCIL_OP_KEEP, // stencil fail 530 VK_STENCIL_OP_ZERO, // depth & stencil pass 531 VK_STENCIL_OP_KEEP, // depth only fail 532 VK_COMPARE_OP_EQUAL, // compare op 533 ~0u, // compare mask 534 ~0u, // write mask 535 STENCIL_REFERENCE); // reference 536} 537 538//! Stencil op that simply increments the buffer with each passing test. 539inline VkStencilOpState stencilOpStateIncrement(void) 540{ 541 return makeStencilOpState( 542 VK_STENCIL_OP_KEEP, // stencil fail 543 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass 544 VK_STENCIL_OP_KEEP, // depth only fail 545 VK_COMPARE_OP_ALWAYS, // compare op 546 ~0u, // compare mask 547 ~0u, // write mask 548 STENCIL_REFERENCE); // reference 549} 550 551//! A few preconfigured vertex attribute configurations 552enum VertexInputConfig 553{ 554 VERTEX_INPUT_NONE = 0u, 555 VERTEX_INPUT_VEC4, 556 VERTEX_INPUT_VEC4_VEC4, 557}; 558 559//! Create a MSAA pipeline, with max per-sample shading 560void preparePipelineWrapper (GraphicsPipelineWrapper& gpw, 561 const std::vector<VkDynamicState>& dynamicState, 562 const PipelineLayoutWrapper& pipelineLayout, 563 const VkRenderPass renderPass, 564 const ShaderWrapper vertexModule, 565 const ShaderWrapper fragmentModule, 566 const deUint32 subpassIndex, 567 const VkViewport& viewport, 568 const VkRect2D scissor, 569 const VkSampleCountFlagBits numSamples, 570 const bool useSampleLocations, 571 const VkSampleLocationsInfoEXT& sampleLocationsInfo, 572 const bool useDepth, 573 const bool useStencil, 574 const VertexInputConfig vertexInputConfig, 575 const VkPrimitiveTopology topology, 576 const VkStencilOpState& stencilOpState, 577 const bool useFragmentShadingRate) 578{ 579 std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions; 580 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions; 581 582 const deUint32 sizeofVec4 = static_cast<deUint32>(sizeof(Vec4)); 583 584 switch (vertexInputConfig) 585 { 586 case VERTEX_INPUT_NONE: 587 break; 588 589 case VERTEX_INPUT_VEC4: 590 vertexInputBindingDescriptions.push_back(makeVertexInputBindingDescription(0u, sizeofVec4, VK_VERTEX_INPUT_RATE_VERTEX)); 591 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u)); 592 break; 593 594 case VERTEX_INPUT_VEC4_VEC4: 595 vertexInputBindingDescriptions.push_back(makeVertexInputBindingDescription(0u, 2u * sizeofVec4, VK_VERTEX_INPUT_RATE_VERTEX)); 596 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u)); 597 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeofVec4)); 598 break; 599 600 default: 601 DE_FATAL("Vertex input config not supported"); 602 break; 603 } 604 605 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 606 { 607 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 608 DE_NULL, // const void* pNext; 609 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 610 static_cast<deUint32>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount; 611 dataOrNullPtr(vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 612 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount; 613 dataOrNullPtr(vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 614 }; 615 616 const VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = 617 { 618 VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType sType; 619 DE_NULL, // const void* pNext; 620 useSampleLocations, // VkBool32 sampleLocationsEnable; 621 sampleLocationsInfo, // VkSampleLocationsInfoEXT sampleLocationsInfo; 622 }; 623 624 const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 625 { 626 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 627 &pipelineSampleLocationsCreateInfo, // const void* pNext; 628 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 629 numSamples, // VkSampleCountFlagBits rasterizationSamples; 630 VK_TRUE, // VkBool32 sampleShadingEnable; 631 1.0f, // float minSampleShading; 632 DE_NULL, // const VkSampleMask* pSampleMask; 633 VK_FALSE, // VkBool32 alphaToCoverageEnable; 634 VK_FALSE // VkBool32 alphaToOneEnable; 635 }; 636 637 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 638 { 639 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 640 DE_NULL, // const void* pNext; 641 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 642 useDepth, // VkBool32 depthTestEnable; 643 true, // VkBool32 depthWriteEnable; 644 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 645 VK_FALSE, // VkBool32 depthBoundsTestEnable; 646 useStencil, // VkBool32 stencilTestEnable; 647 stencilOpState, // VkStencilOpState front; 648 stencilOpState, // VkStencilOpState back; 649 0.0f, // float minDepthBounds; 650 1.0f, // float maxDepthBounds; 651 }; 652 653 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = 654 { 655 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 656 DE_NULL, // const void* pNext; 657 (VkPipelineDynamicStateCreateFlags)0, // VkPipelineDynamicStateCreateFlags flags; 658 static_cast<deUint32>(dynamicState.size()), // uint32_t dynamicStateCount; 659 dataOrNullPtr(dynamicState), // const VkDynamicState* pDynamicStates; 660 }; 661 662 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState 663 { 664 VK_FALSE, // VkBool32 blendEnable 665 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor 666 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor 667 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp 668 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor 669 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor 670 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp 671 VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask 672 | VK_COLOR_COMPONENT_G_BIT 673 | VK_COLOR_COMPONENT_B_BIT 674 | VK_COLOR_COMPONENT_A_BIT 675 }; 676 677 VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoDefault = initVulkanStructure(); 678 colorBlendStateCreateInfoDefault.attachmentCount = 1u; 679 colorBlendStateCreateInfoDefault.pAttachments = &colorBlendAttachmentState; 680 681 const std::vector<VkViewport> viewports { viewport }; 682 const std::vector<VkRect2D> scissors { scissor }; 683 684 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo 685 { 686 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType; 687 DE_NULL, // const void* pNext; 688 { 2, 2 }, // VkExtent2D fragmentSize; 689 { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR }, // VkFragmentShadingRateCombinerOpKHR combinerOps[2]; 690 }; 691 692 gpw.setDefaultTopology(topology) 693 .setDynamicState(&dynamicStateCreateInfo) 694 .setDefaultRasterizationState() 695 .setupVertexInputState(&vertexInputStateInfo) 696 .setupPreRasterizationShaderState(viewports, 697 scissors, 698 pipelineLayout, 699 renderPass, 700 subpassIndex, 701 vertexModule, 702 nullptr, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL, 703 (useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr)) 704 .setupFragmentShaderState(pipelineLayout, 705 renderPass, 706 subpassIndex, 707 fragmentModule, 708 &pipelineDepthStencilStateInfo, 709 &pipelineMultisampleStateInfo) 710 .setupFragmentOutputState(renderPass, subpassIndex, &colorBlendStateCreateInfoDefault, &pipelineMultisampleStateInfo) 711 .setMonolithicPipelineLayout(pipelineLayout) 712 .buildPipeline(); 713} 714 715void preparePipelineWrapperSinglePassColor (GraphicsPipelineWrapper& gpw, 716 const std::vector<VkDynamicState>& dynamicState, 717 const PipelineLayoutWrapper& pipelineLayout, 718 const VkRenderPass renderPass, 719 const ShaderWrapper vertexModule, 720 const ShaderWrapper fragmentModule, 721 const VkViewport& viewport, 722 const VkRect2D scissor, 723 const VkSampleCountFlagBits numSamples, 724 const bool useSampleLocations, 725 const VkSampleLocationsInfoEXT& sampleLocationsInfo, 726 const VertexInputConfig vertexInputConfig, 727 const VkPrimitiveTopology topology, 728 const bool useFragmentShadingRate) 729{ 730 preparePipelineWrapper(gpw, dynamicState, pipelineLayout, renderPass, vertexModule, fragmentModule, 731 /*subpass*/ 0u, viewport, scissor, numSamples, useSampleLocations, sampleLocationsInfo, 732 /*depth test*/ false, /*stencil test*/ false, vertexInputConfig, topology, stencilOpStateIncrement(), useFragmentShadingRate); 733} 734 735//! Utility to build and maintain render pass, framebuffer and related resources. 736//! Use bake() before using the render pass. 737class RenderTarget 738{ 739public: 740 RenderTarget (void) 741 { 742 nextSubpass(); 743 } 744 745 //! Returns an attachment index that is used to reference this attachment later 746 deUint32 addAttachment (const VkImage image, 747 const VkImageView imageView, 748 const VkAttachmentDescriptionFlags flags, 749 const VkFormat format, 750 const VkSampleCountFlagBits numSamples, 751 const VkAttachmentLoadOp loadOp, 752 const VkAttachmentStoreOp storeOp, 753 const VkAttachmentLoadOp stencilLoadOp, 754 const VkAttachmentStoreOp stencilStoreOp, 755 const VkImageLayout initialLayout, 756 const VkImageLayout finalLayout, 757 const VkClearValue clearValue, 758 const VkSampleLocationsInfoEXT* pInitialSampleLocations = DE_NULL) 759 { 760 const deUint32 index = static_cast<deUint32>(m_attachments.size()); 761 762 m_images.push_back(image); 763 m_attachments.push_back(imageView); 764 m_attachmentDescriptions.push_back(makeAttachmentDescription( 765 flags, // VkAttachmentDescriptionFlags flags; 766 format, // VkFormat format; 767 numSamples, // VkSampleCountFlagBits samples; 768 loadOp, // VkAttachmentLoadOp loadOp; 769 storeOp, // VkAttachmentStoreOp storeOp; 770 stencilLoadOp, // VkAttachmentLoadOp stencilLoadOp; 771 stencilStoreOp, // VkAttachmentStoreOp stencilStoreOp; 772 initialLayout, // VkImageLayout initialLayout; 773 finalLayout // VkImageLayout finalLayout; 774 )); 775 m_clearValues.push_back(clearValue); // always add, even if unused 776 777 if (pInitialSampleLocations) 778 { 779 const VkAttachmentSampleLocationsEXT attachmentSampleLocations = 780 { 781 index, // uint32_t attachmentIndex; 782 *pInitialSampleLocations, // VkSampleLocationsInfoEXT sampleLocationsInfo; 783 }; 784 m_attachmentSampleLocations.push_back(attachmentSampleLocations); 785 } 786 787 return index; 788 } 789 790 void addSubpassColorAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout) 791 { 792 m_subpasses.back().colorAttachmentReferences.push_back( 793 makeAttachmentReference(attachmentIndex, subpassLayout)); 794 m_subpasses.back().resolveAttachmentReferences.push_back( 795 makeAttachmentReference(VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_UNDEFINED)); 796 } 797 798 void addSubpassColorAttachmentWithResolve (const deUint32 colorAttachmentIndex, const VkImageLayout colorSubpassLayout, const deUint32 resolveAttachmentIndex, const VkImageLayout resolveSubpassLayout, const VkSampleLocationsInfoEXT* pSampleLocations = DE_NULL) 799 { 800 m_subpasses.back().colorAttachmentReferences.push_back( 801 makeAttachmentReference(colorAttachmentIndex, colorSubpassLayout)); 802 m_subpasses.back().resolveAttachmentReferences.push_back( 803 makeAttachmentReference(resolveAttachmentIndex, resolveSubpassLayout)); 804 805 if (pSampleLocations) 806 { 807 const VkSubpassSampleLocationsEXT subpassSampleLocations = 808 { 809 static_cast<deUint32>(m_subpasses.size() - 1), // uint32_t subpassIndex; 810 *pSampleLocations, // VkSampleLocationsInfoEXT sampleLocationsInfo; 811 }; 812 m_subpassSampleLocations.push_back(subpassSampleLocations); 813 } 814 } 815 816 void addSubpassDepthStencilAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout, const VkSampleLocationsInfoEXT* pSampleLocations = DE_NULL) 817 { 818 m_subpasses.back().depthStencilAttachmentReferences.push_back( 819 makeAttachmentReference(attachmentIndex, subpassLayout)); 820 821 if (pSampleLocations) 822 { 823 const VkSubpassSampleLocationsEXT subpassSampleLocations = 824 { 825 static_cast<deUint32>(m_subpasses.size() - 1), // uint32_t subpassIndex; 826 *pSampleLocations, // VkSampleLocationsInfoEXT sampleLocationsInfo; 827 }; 828 m_subpassSampleLocations.push_back(subpassSampleLocations); 829 } 830 } 831 832 void addSubpassInputAttachment (const deUint32 attachmentIndex, const VkImageLayout subpassLayout) 833 { 834 m_subpasses.back().inputAttachmentReferences.push_back( 835 makeAttachmentReference(attachmentIndex, subpassLayout)); 836 } 837 838 void addSubpassPreserveAttachment (const deUint32 attachmentIndex) 839 { 840 m_subpasses.back().preserveAttachmentReferences.push_back(attachmentIndex); 841 } 842 843 void nextSubpass (void) 844 { 845 m_subpasses.push_back(SubpassDescription()); 846 } 847 848 //! Create a RenderPass and Framebuffer based on provided attachments 849 void bake (const DeviceInterface& vk, 850 const VkDevice device, 851 const PipelineConstructionType pipelineConstructionType, 852 const UVec2& framebufferSize) 853 { 854 const deUint32 numSubpasses = static_cast<deUint32>(m_subpasses.size()); 855 856 std::vector<VkSubpassDescription> subpassDescriptions; 857 std::vector<VkSubpassDependency> subpassDependencies; 858 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 859 { 860 const SubpassDescription& sd = m_subpasses[subpassNdx]; 861 const VkSubpassDescription description = 862 { 863 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 864 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 865 static_cast<deUint32>(sd.inputAttachmentReferences.size()), // deUint32 inputAttachmentCount; 866 dataOrNullPtr(sd.inputAttachmentReferences), // const VkAttachmentReference* pInputAttachments; 867 static_cast<deUint32>(sd.colorAttachmentReferences.size()), // deUint32 colorAttachmentCount; 868 dataOrNullPtr(sd.colorAttachmentReferences), // const VkAttachmentReference* pColorAttachments; 869 dataOrNullPtr(sd.resolveAttachmentReferences), // const VkAttachmentReference* pResolveAttachments; 870 dataOrNullPtr(sd.depthStencilAttachmentReferences), // const VkAttachmentReference* pDepthStencilAttachment; 871 static_cast<deUint32>(sd.preserveAttachmentReferences.size()), // deUint32 preserveAttachmentCount; 872 dataOrNullPtr(sd.preserveAttachmentReferences) // const deUint32* pPreserveAttachments; 873 }; 874 subpassDescriptions.push_back(description); 875 876 // Add a very coarse dependency enforcing sequential ordering of subpasses 877 if (subpassNdx > 0) 878 { 879 static const VkAccessFlags accessAny = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT 880 | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT 881 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT 882 | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT 883 | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 884 const VkSubpassDependency dependency = 885 { 886 subpassNdx - 1, // uint32_t srcSubpass; 887 subpassNdx, // uint32_t dstSubpass; 888 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // VkPipelineStageFlags srcStageMask; 889 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, // VkPipelineStageFlags dstStageMask; 890 accessAny, // VkAccessFlags srcAccessMask; 891 accessAny, // VkAccessFlags dstAccessMask; 892 (VkDependencyFlags)0, // VkDependencyFlags dependencyFlags; 893 }; 894 subpassDependencies.push_back(dependency); 895 } 896 } 897 // add a final dependency to synchronize results for the copy commands that will follow the renderpass 898 const VkSubpassDependency finalDependency = { 899 numSubpasses - 1, // uint32_t srcSubpass; 900 VK_SUBPASS_EXTERNAL, // uint32_t dstSubpass; 901 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask; 902 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask; 903 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 904 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 905 (VkDependencyFlags)0, // VkDependencyFlags dependencyFlags; 906 }; 907 subpassDependencies.push_back(finalDependency); 908 909 const VkRenderPassCreateInfo renderPassInfo = 910 { 911 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 912 DE_NULL, // const void* pNext; 913 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 914 static_cast<deUint32>(m_attachmentDescriptions.size()), // deUint32 attachmentCount; 915 dataOrNullPtr(m_attachmentDescriptions), // const VkAttachmentDescription* pAttachments; 916 static_cast<deUint32>(subpassDescriptions.size()), // deUint32 subpassCount; 917 dataOrNullPtr(subpassDescriptions), // const VkSubpassDescription* pSubpasses; 918 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount; 919 dataOrNullPtr(subpassDependencies) // const VkSubpassDependency* pDependencies; 920 }; 921 922 m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, device, &renderPassInfo); 923 m_renderPass.createFramebuffer(vk, device, static_cast<deUint32>(m_attachments.size()), dataOrNullPtr(m_images), dataOrNullPtr(m_attachments), framebufferSize.x(), framebufferSize.y()); 924 } 925 926 const RenderPassWrapper& getRenderPassWrapper (void) const 927 { 928 return m_renderPass; 929 } 930 931 VkRenderPass getRenderPass (void) const 932 { 933 return *m_renderPass; 934 } 935 936 VkFramebuffer getFramebuffer(void) const 937 { 938 return m_renderPass.getFramebuffer(); 939 } 940 941 void recordBeginRenderPass (const DeviceInterface& vk, 942 const VkCommandBuffer cmdBuffer, 943 const VkRect2D& renderArea, 944 const VkSubpassContents subpassContents) const 945 { 946 const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo = 947 { 948 VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT, // VkStructureType sType; 949 DE_NULL, // const void* pNext; 950 static_cast<deUint32>(m_attachmentSampleLocations.size()), // uint32_t attachmentInitialSampleLocationsCount; 951 dataOrNullPtr(m_attachmentSampleLocations), // const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; 952 static_cast<deUint32>(m_subpassSampleLocations.size()), // uint32_t postSubpassSampleLocationsCount; 953 dataOrNullPtr(m_subpassSampleLocations), // const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; 954 }; 955 m_renderPass.begin(vk, cmdBuffer, renderArea, static_cast<deUint32>(m_clearValues.size()), dataOrNullPtr(m_clearValues), subpassContents, &renderPassSampleLocationsBeginInfo); 956 } 957 958 void nextSubpass (const DeviceInterface& vk, const VkCommandBuffer cmdBuffer, const VkSubpassContents subpassContents) const 959 { 960 m_renderPass.nextSubpass(vk, cmdBuffer, subpassContents); 961 } 962 963 void endRenderPass (const DeviceInterface& vk, const VkCommandBuffer cmdBuffer) const 964 { 965 m_renderPass.end(vk, cmdBuffer); 966 } 967 968private: 969 struct SubpassDescription 970 { 971 std::vector<VkAttachmentReference> inputAttachmentReferences; 972 std::vector<VkAttachmentReference> colorAttachmentReferences; 973 std::vector<VkAttachmentReference> resolveAttachmentReferences; 974 std::vector<VkAttachmentReference> depthStencilAttachmentReferences; 975 std::vector<deUint32> preserveAttachmentReferences; 976 }; 977 978 std::vector<SubpassDescription> m_subpasses; 979 std::vector<VkImage> m_images; 980 std::vector<VkImageView> m_attachments; 981 std::vector<VkAttachmentDescription> m_attachmentDescriptions; 982 std::vector<VkClearValue> m_clearValues; 983 std::vector<VkAttachmentSampleLocationsEXT> m_attachmentSampleLocations; 984 std::vector<VkSubpassSampleLocationsEXT> m_subpassSampleLocations; 985 RenderPassWrapper m_renderPass; 986 987 // No copying allowed 988 RenderTarget (const RenderTarget&); 989 RenderTarget& operator=(const RenderTarget&); 990}; 991 992void recordImageBarrier (const DeviceInterface& vk, 993 const VkCommandBuffer cmdBuffer, 994 const VkImage image, 995 const VkImageAspectFlags aspect, 996 const VkPipelineStageFlags srcStageMask, 997 const VkPipelineStageFlags dstStageMask, 998 const VkAccessFlags srcAccessMask, 999 const VkAccessFlags dstAccessMask, 1000 const VkImageLayout oldLayout, 1001 const VkImageLayout newLayout, 1002 const VkSampleLocationsInfoEXT* pSampleLocationsInfo = DE_NULL) 1003{ 1004 const VkImageMemoryBarrier barrier = 1005 { 1006 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1007 pSampleLocationsInfo, // const void* pNext; 1008 srcAccessMask, // VkAccessFlags srcAccessMask; 1009 dstAccessMask, // VkAccessFlags dstAccessMask; 1010 oldLayout, // VkImageLayout oldLayout; 1011 newLayout, // VkImageLayout newLayout; 1012 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1013 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1014 image, // VkImage image; 1015 makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u), // VkImageSubresourceRange subresourceRange; 1016 }; 1017 1018 vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier); 1019} 1020 1021void recordWaitEventWithImage (const DeviceInterface& vk, 1022 const VkCommandBuffer cmdBuffer, 1023 const VkEvent event, 1024 const VkImage image, 1025 const VkImageAspectFlags aspect, 1026 const VkPipelineStageFlags srcStageMask, 1027 const VkPipelineStageFlags dstStageMask, 1028 const VkAccessFlags srcAccessMask, 1029 const VkAccessFlags dstAccessMask, 1030 const VkImageLayout oldLayout, 1031 const VkImageLayout newLayout, 1032 const VkSampleLocationsInfoEXT* pSampleLocationsInfo = DE_NULL) 1033{ 1034 const VkImageMemoryBarrier barrier = 1035 { 1036 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 1037 pSampleLocationsInfo, // const void* pNext; 1038 srcAccessMask, // VkAccessFlags srcAccessMask; 1039 dstAccessMask, // VkAccessFlags dstAccessMask; 1040 oldLayout, // VkImageLayout oldLayout; 1041 newLayout, // VkImageLayout newLayout; 1042 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1043 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1044 image, // VkImage image; 1045 makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u), // VkImageSubresourceRange subresourceRange; 1046 }; 1047 1048 vk.cmdWaitEvents( 1049 cmdBuffer, // VkCommandBuffer commandBuffer, 1050 1u, // uint32_t eventCount, 1051 &event, // const VkEvent* pEvents, 1052 srcStageMask, // VkPipelineStageFlags srcStageMask, 1053 dstStageMask, // VkPipelineStageFlags dstStageMask, 1054 0u, // uint32_t memoryBarrierCount, 1055 DE_NULL, // const VkMemoryBarrier* pMemoryBarriers, 1056 0u, // uint32_t bufferMemoryBarrierCount, 1057 DE_NULL, // const VkBufferMemoryBarrier* pBufferMemoryBarriers, 1058 1u, // uint32_t imageMemoryBarrierCount, 1059 &barrier); // const VkImageMemoryBarrier* pImageMemoryBarriers); 1060} 1061 1062void recordCopyImageToBuffer (const DeviceInterface& vk, 1063 const VkCommandBuffer cmdBuffer, 1064 const UVec2& imageSize, 1065 const VkImage srcImage, 1066 const VkBuffer dstBuffer) 1067{ 1068 // Resolve image -> host buffer 1069 { 1070 const VkBufferImageCopy region = 1071 { 1072 0ull, // VkDeviceSize bufferOffset; 1073 0u, // uint32_t bufferRowLength; 1074 0u, // uint32_t bufferImageHeight; 1075 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 1076 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 1077 makeExtent3D(imageSize.x(), imageSize.y(), 1u), // VkExtent3D imageExtent; 1078 }; 1079 1080 vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, ®ion); 1081 } 1082 // Buffer write barrier 1083 { 1084 const VkBufferMemoryBarrier barrier = 1085 { 1086 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1087 DE_NULL, // const void* pNext; 1088 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1089 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1090 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1091 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1092 dstBuffer, // VkBuffer buffer; 1093 0ull, // VkDeviceSize offset; 1094 VK_WHOLE_SIZE, // VkDeviceSize size; 1095 }; 1096 1097 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 1098 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u); 1099 } 1100} 1101 1102void recordClearAttachments (const DeviceInterface& vk, 1103 const VkCommandBuffer cmdBuffer, 1104 const deUint32 colorAttachment, 1105 const VkClearValue& colorClearValue, 1106 const VkImageAspectFlags depthStencilAspect, 1107 const VkClearValue& depthStencilClearValue, 1108 const VkRect2D& clearRect) 1109{ 1110 std::vector<VkClearAttachment> attachments; 1111 1112 const VkClearRect rect = 1113 { 1114 clearRect, // VkRect2D rect; 1115 0u, // uint32_t baseArrayLayer; 1116 1u, // uint32_t layerCount; 1117 }; 1118 1119 // Clear color 1120 { 1121 const VkClearAttachment attachment = 1122 { 1123 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1124 colorAttachment, // uint32_t colorAttachment; 1125 colorClearValue, // VkClearValue clearValue; 1126 }; 1127 attachments.push_back(attachment); 1128 } 1129 1130 if ((depthStencilAspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0u) 1131 { 1132 const VkClearAttachment attachment = 1133 { 1134 depthStencilAspect, // VkImageAspectFlags aspectMask; 1135 VK_ATTACHMENT_UNUSED, // uint32_t colorAttachment; 1136 depthStencilClearValue, // VkClearValue clearValue; 1137 }; 1138 attachments.push_back(attachment); 1139 } 1140 1141 vk.cmdClearAttachments(cmdBuffer, static_cast<deUint32>(attachments.size()), dataOrNullPtr(attachments), 1u, &rect); 1142} 1143 1144//! Suitable for executing in a render pass, no queries 1145void beginSecondaryCommandBuffer (const DeviceInterface& vk, 1146 const VkCommandBuffer commandBuffer, 1147 const RenderPassWrapper& renderPass, 1148 const deUint32 subpass, 1149 const VkSampleCountFlagBits samples, 1150 const PipelineConstructionType pct) 1151{ 1152 DE_UNREF(samples); 1153 DE_UNREF(pct); 1154 VkCommandBufferInheritanceInfo inheritanceInfo = 1155 { 1156 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType; 1157 DE_NULL, // const void* pNext; 1158 *renderPass, // VkRenderPass renderPass; 1159 subpass, // uint32_t subpass; 1160 renderPass.getFramebuffer(), // VkFramebuffer framebuffer; 1161 VK_FALSE, // VkBool32 occlusionQueryEnable; 1162 (VkQueryControlFlags)0, // VkQueryControlFlags queryFlags; 1163 (VkQueryPipelineStatisticFlags)0, // VkQueryPipelineStatisticFlags pipelineStatistics; 1164 }; 1165 1166 const VkCommandBufferBeginInfo beginInfo = 1167 { 1168 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 1169 DE_NULL, // const void* pNext; 1170 (VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT 1171 |VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT), // VkCommandBufferUsageFlags flags; 1172 &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; 1173 }; 1174 1175#ifndef CTS_USES_VULKANSC 1176 vk::VkCommandBufferInheritanceRenderingInfo inheritanceRenderingInfo = vk::initVulkanStructure(); 1177 inheritanceRenderingInfo.flags = (VkRenderingFlags)0u; 1178 inheritanceRenderingInfo.viewMask = 0x0; 1179 inheritanceRenderingInfo.rasterizationSamples = samples; 1180 std::vector<vk::VkFormat> colorFormats; 1181 if (isConstructionTypeShaderObject(pct)) 1182 { 1183 renderPass.fillInheritanceRenderingInfo(subpass, &colorFormats, &inheritanceRenderingInfo); 1184 inheritanceInfo.pNext = &inheritanceRenderingInfo; 1185 } 1186#endif 1187 1188 VK_CHECK(vk.beginCommandBuffer(commandBuffer, &beginInfo)); 1189} 1190 1191//! Verify results of a VkPhysicalDeviceSampleLocationsPropertiesEXT query with VkPhysicalDeviceProperties2KHR 1192tcu::TestStatus testQuerySampleLocationProperties (Context& context) 1193{ 1194 const VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties = getSampleLocationsPropertiesEXT(context); 1195 1196 context.getTestContext().getLog() 1197 << tcu::TestLog::Section("VkPhysicalDeviceSampleLocationsPropertiesEXT", "Query results") 1198 << tcu::TestLog::Message << sampleLocationsProperties << tcu::TestLog::EndMessage 1199 << tcu::TestLog::EndSection; 1200 1201 const VkSampleCountFlags allowedSampleCounts = (VK_SAMPLE_COUNT_2_BIT | 1202 VK_SAMPLE_COUNT_4_BIT | 1203 VK_SAMPLE_COUNT_8_BIT | 1204 VK_SAMPLE_COUNT_16_BIT | 1205 VK_SAMPLE_COUNT_32_BIT | 1206 VK_SAMPLE_COUNT_64_BIT); 1207 1208 if ((sampleLocationsProperties.sampleLocationSampleCounts & allowedSampleCounts) == 0) 1209 { 1210 return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationSampleCounts should specify at least one MSAA sample count"); 1211 } 1212 1213 if (sampleLocationsProperties.maxSampleLocationGridSize.width == 0u || 1214 sampleLocationsProperties.maxSampleLocationGridSize.height == 0u || 1215 sampleLocationsProperties.maxSampleLocationGridSize.width > 16384u || // max not specified, but try to catch nonsense values like -1 1216 sampleLocationsProperties.maxSampleLocationGridSize.height > 16384u) 1217 { 1218 return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: maxSampleLocationGridSize must be at least (1,1) size"); 1219 } 1220 1221 for (int i = 0; i < 2; ++i) 1222 { 1223 if (sampleLocationsProperties.sampleLocationCoordinateRange[i] < 0.0f || 1224 sampleLocationsProperties.sampleLocationCoordinateRange[i] > 1.0f) 1225 { 1226 return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationCoordinateRange[] values must be in [0, 1] range"); 1227 } 1228 } 1229 1230 if (sampleLocationsProperties.sampleLocationSubPixelBits == 0u || 1231 sampleLocationsProperties.sampleLocationSubPixelBits > 64u) // max not specified, but try to catch nonsense values 1232 { 1233 return tcu::TestStatus::fail("VkPhysicalDeviceSampleLocationsPropertiesEXT: sampleLocationSubPixelBits should be greater than 0"); 1234 } 1235 1236 return tcu::TestStatus::pass("Pass"); 1237} 1238 1239//! Verify results of vkGetPhysicalDeviceMultisamplePropertiesEXT queries 1240tcu::TestStatus testQueryMultisampleProperties (Context& context) 1241{ 1242 const InstanceInterface& vki = context.getInstanceInterface(); 1243 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 1244 tcu::TestLog& log = context.getTestContext().getLog(); 1245 1246 const VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties = getSampleLocationsPropertiesEXT(context); 1247 1248 const VkSampleCountFlagBits sampleCountRange[] = 1249 { 1250 VK_SAMPLE_COUNT_1_BIT, 1251 VK_SAMPLE_COUNT_2_BIT, 1252 VK_SAMPLE_COUNT_4_BIT, 1253 VK_SAMPLE_COUNT_8_BIT, 1254 VK_SAMPLE_COUNT_16_BIT, 1255 VK_SAMPLE_COUNT_32_BIT, 1256 VK_SAMPLE_COUNT_64_BIT, 1257 }; 1258 1259 bool allOk = true; 1260 1261 for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples) 1262 { 1263 VkMultisamplePropertiesEXT multisampleProperties = 1264 { 1265 VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT, // VkStructureType sType; 1266 DE_NULL, // void* pNext; 1267 VkExtent2D(), // VkExtent2D maxSampleLocationGridSize; 1268 }; 1269 1270 vki.getPhysicalDeviceMultisamplePropertiesEXT(physicalDevice, *pLoopNumSamples, &multisampleProperties); 1271 1272 log << tcu::TestLog::Section("getPhysicalDeviceMultisamplePropertiesEXT", "Query results") 1273 << tcu::TestLog::Message << "Sample count: " << *pLoopNumSamples << tcu::TestLog::EndMessage 1274 << tcu::TestLog::Message << multisampleProperties << tcu::TestLog::EndMessage; 1275 1276 const bool isSupportedSampleCount = (*pLoopNumSamples & sampleLocationsProperties.sampleLocationSampleCounts) != 0; 1277 1278 if (isSupportedSampleCount) 1279 { 1280 if (!(multisampleProperties.maxSampleLocationGridSize.width >= sampleLocationsProperties.maxSampleLocationGridSize.width && 1281 multisampleProperties.maxSampleLocationGridSize.height >= sampleLocationsProperties.maxSampleLocationGridSize.height)) 1282 { 1283 allOk = false; 1284 log << tcu::TestLog::Message 1285 << "FAIL: Grid size should be the same or larger than VkPhysicalDeviceSampleLocationsPropertiesEXT::maxSampleLocationGridSize" 1286 << tcu::TestLog::EndMessage; 1287 } 1288 } 1289 else 1290 { 1291 if (!(multisampleProperties.maxSampleLocationGridSize.width == 0u && 1292 multisampleProperties.maxSampleLocationGridSize.height == 0u)) 1293 { 1294 allOk = false; 1295 log << tcu::TestLog::Message << "FAIL: Expected (0, 0) grid size" << tcu::TestLog::EndMessage; 1296 } 1297 } 1298 1299 log << tcu::TestLog::EndSection; 1300 } 1301 1302 return allOk ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some values were incorrect"); 1303} 1304 1305// These tests only use a color attachment and focus on per-sample data 1306namespace VerifySamples 1307{ 1308 1309//! Data layout used in verify sample locations and interpolation cases 1310namespace SampleDataSSBO 1311{ 1312 1313static VkDeviceSize STATIC_SIZE = 6 * sizeof(deUint32); 1314 1315static UVec2& renderSize (void* const basePtr) { return *reinterpret_cast<UVec2*> (static_cast<deUint8*>(basePtr) + 0 * sizeof(deUint32)); } 1316static UVec2& gridSize (void* const basePtr) { return *reinterpret_cast<UVec2*> (static_cast<deUint8*>(basePtr) + 2 * sizeof(deUint32)); } 1317static deUint32& samplesPerPixel (void* const basePtr) { return *reinterpret_cast<deUint32*> (static_cast<deUint8*>(basePtr) + 4 * sizeof(deUint32)); } 1318 1319template<typename T> 1320static T* sampleData (void* const basePtr) { DE_STATIC_ASSERT(sizeof(T) == sizeof(Vec2)); 1321 return reinterpret_cast<T*> (static_cast<deUint8*>(basePtr) + STATIC_SIZE); } 1322 1323} // SampleDataSSBO 1324 1325enum TestOptionFlagBits 1326{ 1327 TEST_OPTION_DYNAMIC_STATE_BIT = 0x1, //!< Use dynamic pipeline state to pass in sample locations 1328 TEST_OPTION_CLOSELY_PACKED_BIT = 0x2, //!< Place samples as close as possible to each other 1329 TEST_OPTION_FRAGMENT_SHADING_RATE_BIT = 0x4, //!< Use VK_KHR_fragment_shading_rate 1330 TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT = 0x8 //!< Use variable sample locations 1331}; 1332typedef deUint32 TestOptionFlags; 1333 1334struct TestParams 1335{ 1336 PipelineConstructionType pipelineConstructionType; 1337 VkSampleCountFlagBits numSamples; 1338 TestOptionFlags options; 1339}; 1340 1341void checkSupportVerifyTests (Context& context, const TestParams params) 1342{ 1343 checkSupportSampleLocations(context); 1344 1345 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 1346 1347 if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & params.numSamples) == 0u) 1348 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported"); 1349 1350 if ((getSampleLocationsPropertiesEXT(context).sampleLocationSampleCounts & params.numSamples) == 0u) 1351 TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: sample count not supported"); 1352 1353 if (TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & params.options) 1354 checkFragmentShadingRateRequirements(context, params.numSamples); 1355 1356 if (TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT & params.options && !getSampleLocationsPropertiesEXT(context).variableSampleLocations) 1357 TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: variableSampleLocations not supported"); 1358 1359 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType); 1360} 1361 1362std::string declareSampleDataSSBO (void) 1363{ 1364 std::ostringstream str; 1365 str << "layout(set = 0, binding = 0, std430) readonly buffer SampleData {\n" // make sure this matches SampleDataSSBO definition 1366 << " uvec2 renderSize;\n" 1367 << " uvec2 gridSize;\n" 1368 << " uint samplesPerPixel;\n" 1369 << " // padding 1-uint size;\n" 1370 << " vec2 data[];\n" 1371 << "} sb_data;\n"; 1372 return str.str(); 1373} 1374 1375void addProgramsVerifyLocationGeometry (SourceCollections& programCollection, const TestParams) 1376{ 1377 // Vertex shader 1378 { 1379 std::ostringstream src; 1380 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1381 << "\n" 1382 << "layout(location = 0) in vec4 in_position;\n" 1383 << "\n" 1384 << "out gl_PerVertex {\n" 1385 << " vec4 gl_Position;\n" 1386 << "};\n" 1387 << "\n" 1388 << "void main(void)\n" 1389 << "{\n" 1390 << " gl_Position = in_position;\n" 1391 << "}\n"; 1392 1393 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 1394 } 1395 1396 // Fragment shader 1397 { 1398 std::ostringstream src; 1399 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1400 << "\n" 1401 << "layout(location = 0) out vec4 o_color;\n" 1402 << "\n" 1403 << declareSampleDataSSBO() 1404 << "\n" 1405 << "void main(void)\n" 1406 << "{\n" 1407 << " uvec2 fragCoord = uvec2(gl_FragCoord.xy);\n" 1408 << " uint index = (fragCoord.y * sb_data.renderSize.x + fragCoord.x) * sb_data.samplesPerPixel + gl_SampleID;\n" 1409 << "\n" 1410 << " if (gl_PrimitiveID == index)\n" 1411 << " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 1412 << " else\n" 1413 << " o_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 1414 << "}\n"; 1415 1416 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 1417 } 1418} 1419 1420void addProgramsVerifyInterpolation (SourceCollections& programCollection, const TestParams) 1421{ 1422 // Vertex shader 1423 { 1424 std::ostringstream src; 1425 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1426 << "\n" 1427 << "layout(location = 0) in vec4 in_position;\n" 1428 << "layout(location = 0) out vec2 o_position;\n" 1429 << "\n" 1430 << "out gl_PerVertex {\n" 1431 << " vec4 gl_Position;\n" 1432 << "};\n" 1433 << "\n" 1434 << "void main(void)\n" 1435 << "{\n" 1436 << " gl_Position = in_position;\n" 1437 << " o_position = in_position.xy;\n" // user-data that will be interpolated 1438 << "}\n"; 1439 1440 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 1441 } 1442 1443 // Fragment shader 1444 { 1445 std::ostringstream src; 1446 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1447 << "\n" 1448 << "layout(location = 0) sample in vec2 in_value;\n" 1449 << "layout(location = 0) out vec4 o_color;\n" 1450 << "\n" 1451 << declareSampleDataSSBO() 1452 << "\n" 1453 << "void main(void)\n" 1454 << "{\n" 1455 << " uvec2 fragCoord = uvec2(gl_FragCoord.xy);\n" 1456 << " uint index = (fragCoord.y * sb_data.renderSize.x + fragCoord.x) * sb_data.samplesPerPixel + gl_SampleID;\n" 1457 << " vec2 diff = abs(sb_data.data[index] - in_value);\n" 1458 << " vec2 threshold = vec2(0.002);\n" 1459 << "\n" 1460 << " if (all(lessThan(diff, threshold)))\n" 1461 << " o_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 1462 << " else\n" 1463 << " o_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 1464 << "}\n"; 1465 1466 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 1467 } 1468} 1469 1470class TestBase : public TestInstance 1471{ 1472public: 1473 TestBase (Context& context, const TestParams params) 1474 : TestInstance (context) 1475 , m_params (params) 1476 , m_sampleLocationsProperties (getSampleLocationsPropertiesEXT(context)) 1477 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 1478 , m_numVertices (0) 1479 , m_currentGridNdx (0) 1480 { 1481 VkMultisamplePropertiesEXT multisampleProperties = 1482 { 1483 VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT, // VkStructureType sType; 1484 DE_NULL, // void* pNext; 1485 VkExtent2D(), // VkExtent2D maxSampleLocationGridSize; 1486 }; 1487 1488 m_context.getInstanceInterface().getPhysicalDeviceMultisamplePropertiesEXT(m_context.getPhysicalDevice(), m_params.numSamples, &multisampleProperties); 1489 1490 // Generate grid size combinations 1491 for (deUint32 y = multisampleProperties.maxSampleLocationGridSize.height; y >= 1u; y >>= 1) 1492 for (deUint32 x = multisampleProperties.maxSampleLocationGridSize.width; x >= 1u; x >>= 1) 1493 { 1494 DE_ASSERT(multisampleProperties.maxSampleLocationGridSize.width % x == 0u); 1495 DE_ASSERT(multisampleProperties.maxSampleLocationGridSize.height % y == 0u); 1496 m_gridSizes.push_back(UVec2(x, y)); 1497 } 1498 } 1499 1500 tcu::TestStatus iterate (void) 1501 { 1502 // Will be executed several times, for all possible pixel grid sizes 1503 if (!(currentGridSize().x() >= 1 && currentGridSize().y() >= 1)) 1504 return tcu::TestStatus::fail("maxSampleLocationGridSize is invalid"); 1505 1506 // Prepare the pixel grid 1507 { 1508 const deUint32 pixelGridRepetitions = 2; // just to make sure the pattern is consistently applied across the framebuffer 1509 m_renderSize = UVec2(pixelGridRepetitions * currentGridSize().x(), 1510 pixelGridRepetitions * currentGridSize().y()); 1511 m_pixelGrid = MovePtr<MultisamplePixelGrid>(new MultisamplePixelGrid(currentGridSize(), m_params.numSamples)); 1512 1513 if ((m_params.options & TEST_OPTION_CLOSELY_PACKED_BIT) != 0u) 1514 fillSampleLocationsPacked(*m_pixelGrid, m_sampleLocationsProperties.sampleLocationSubPixelBits); 1515 else 1516 fillSampleLocationsRandom(*m_pixelGrid, m_sampleLocationsProperties.sampleLocationSubPixelBits); 1517 1518 logPixelGrid (m_context.getTestContext().getLog(), m_sampleLocationsProperties, *m_pixelGrid); 1519 } 1520 1521 // Create images 1522 { 1523 const DeviceInterface& vk = m_context.getDeviceInterface(); 1524 const VkDevice device = m_context.getDevice(); 1525 Allocator& allocator = m_context.getDefaultAllocator(); 1526 1527 // Images and staging buffers 1528 1529 m_colorImage = makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, m_params.numSamples, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); 1530 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any); 1531 m_colorImageView = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 1532 1533 m_resolveImage = makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 1534 m_resolveImageAlloc = bindImage(vk, device, allocator, *m_resolveImage, MemoryRequirement::Any); 1535 m_resolveImageView = makeImageView(vk, device, *m_resolveImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 1536 1537 const VkDeviceSize colorBufferSize = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(m_colorFormat)); 1538 m_colorBuffer = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 1539 m_colorBufferAlloc = bindBuffer(vk, device, allocator, *m_colorBuffer, MemoryRequirement::HostVisible); 1540 } 1541 1542 if (!testPixelGrid()) 1543 return tcu::TestStatus::fail("Fail"); 1544 1545 if (shrinkCurrentGrid()) 1546 return tcu::TestStatus::incomplete(); 1547 else 1548 return tcu::TestStatus::pass("Pass"); 1549 } 1550 1551protected: 1552 //! Return true if the test passed the current grid size 1553 virtual bool testPixelGrid (void) = 0; 1554 1555 const UVec2& currentGridSize (void) 1556 { 1557 return m_gridSizes[m_currentGridNdx]; 1558 } 1559 1560 //! Return false if the grid is already at (1, 1) size 1561 bool shrinkCurrentGrid (void) 1562 { 1563 if (m_gridSizes.size() <= m_currentGridNdx + 1) 1564 return false; 1565 1566 ++m_currentGridNdx; 1567 return true; 1568 } 1569 1570 void drawSinglePass (const VertexInputConfig vertexInputConfig) 1571 { 1572 DE_ASSERT(m_descriptorSetLayout); 1573 1574 const InstanceInterface& vki = m_context.getInstanceInterface(); 1575 const DeviceInterface& vk = m_context.getDeviceInterface(); 1576 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 1577 const VkDevice device = m_context.getDevice(); 1578 const VkViewport viewport = makeViewport(m_renderSize); 1579 const VkRect2D renderArea = makeRect2D(m_renderSize); 1580 const VkRect2D scissor = makeRect2D(m_renderSize); 1581 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 1582 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 1583 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vk, device, *m_descriptorSetLayout); 1584 1585 const bool useDynamicStateSampleLocations = ((m_params.options & TEST_OPTION_DYNAMIC_STATE_BIT) != 0u); 1586 const bool useFragmentShadingRate = ((m_params.options & TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) != 0u); 1587 const VkSampleLocationsInfoEXT sampleLocationsInfo = makeSampleLocationsInfo(*m_pixelGrid); 1588 1589 RenderTarget rt; 1590 1591 rt.addAttachment( 1592 *m_colorImage, // VkImage image, 1593 *m_colorImageView, // VkImageView imageView, 1594 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 1595 m_colorFormat, // VkFormat format, 1596 m_params.numSamples, // VkSampleCountFlagBits numSamples, 1597 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 1598 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 1599 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 1600 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 1601 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 1602 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 1603 makeClearValueColor(CLEAR_COLOR_0)); // VkClearValue clearValue, 1604 1605 rt.addAttachment( 1606 *m_resolveImage, // VkImage image 1607 *m_resolveImageView, // VkImageView imageView, 1608 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 1609 m_colorFormat, // VkFormat format, 1610 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits numSamples, 1611 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp, 1612 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 1613 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 1614 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 1615 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 1616 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout finalLayout, 1617 VkClearValue()); // VkClearValue clearValue, 1618 1619 if (TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT & m_params.options) 1620 { 1621 rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1622 1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, &sampleLocationsInfo); 1623 } 1624 else 1625 { 1626 rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1627 1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 1628 } 1629 1630 rt.bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 1631 1632 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 1633 1634 if (useDynamicStateSampleLocations) 1635 { 1636 std::vector<VkDynamicState> dynamicState; 1637 dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT); 1638 1639 preparePipelineWrapperSinglePassColor( 1640 pipeline, dynamicState, pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, viewport, scissor, 1641 m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(), vertexInputConfig, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, useFragmentShadingRate); 1642 } 1643 else 1644 { 1645 preparePipelineWrapperSinglePassColor( 1646 pipeline, std::vector<VkDynamicState>(), pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, viewport, scissor, 1647 m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo, vertexInputConfig, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, useFragmentShadingRate); 1648 } 1649 1650 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex())); 1651 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1652 1653 beginCommandBuffer(vk, *cmdBuffer); 1654 1655 rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE); 1656 1657 vk.cmdBindVertexBuffers(*cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO); 1658 pipeline.bind(*cmdBuffer); 1659 1660 if (useDynamicStateSampleLocations) 1661 vk.cmdSetSampleLocationsEXT(*cmdBuffer, &sampleLocationsInfo); 1662 1663 if (m_descriptorSet) 1664 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL); 1665 1666 vk.cmdDraw(*cmdBuffer, m_numVertices, 1u, 0u, 0u); 1667 rt.endRenderPass(vk, *cmdBuffer); 1668 1669 recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer); 1670 1671 endCommandBuffer(vk, *cmdBuffer); 1672 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer); 1673 1674 invalidateAlloc(vk, device, *m_colorBufferAlloc); 1675 } 1676 1677 void createSampleDataBufferAndDescriptors (const VkDeviceSize bufferSize) 1678 { 1679 // Make sure the old descriptor set is destroyed before we destroy its pool 1680 m_descriptorSet = Move<VkDescriptorSet>(); 1681 1682 const DeviceInterface& vk = m_context.getDeviceInterface(); 1683 const VkDevice device = m_context.getDevice(); 1684 Allocator& allocator = m_context.getDefaultAllocator(); 1685 1686 m_sampleDataBuffer = makeBuffer(vk, device, bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1687 m_sampleDataBufferAlloc = bindBuffer(vk, device, allocator, *m_sampleDataBuffer, MemoryRequirement::HostVisible); 1688 1689 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 1690 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 1691 .build(vk, device); 1692 1693 m_descriptorPool = DescriptorPoolBuilder() 1694 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 1695 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1696 1697 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout); 1698 1699 const VkDescriptorBufferInfo bufferDescriptorInfo = makeDescriptorBufferInfo(*m_sampleDataBuffer, 0ull, bufferSize); 1700 DescriptorSetUpdateBuilder() 1701 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescriptorInfo) 1702 .update(vk, device); 1703 1704 SampleDataSSBO::renderSize (m_sampleDataBufferAlloc->getHostPtr()) = m_renderSize; 1705 SampleDataSSBO::gridSize (m_sampleDataBufferAlloc->getHostPtr()) = m_pixelGrid->size(); 1706 SampleDataSSBO::samplesPerPixel (m_sampleDataBufferAlloc->getHostPtr()) = m_pixelGrid->samplesPerPixel(); 1707 1708 flushAlloc(vk, device, *m_sampleDataBufferAlloc); 1709 } 1710 1711 template<typename Vertex> 1712 void createVertexBuffer (const std::vector<Vertex>& vertices) 1713 { 1714 const DeviceInterface& vk = m_context.getDeviceInterface(); 1715 const VkDevice device = m_context.getDevice(); 1716 Allocator& allocator = m_context.getDefaultAllocator(); 1717 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(vertices.size() * sizeof(vertices[0])); 1718 1719 m_numVertices = static_cast<deUint32>(vertices.size()); 1720 m_vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1721 m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible); 1722 1723 deMemcpy(m_vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize)); 1724 flushAlloc(vk, device, *m_vertexBufferAlloc); 1725 } 1726 1727 const TestParams m_params; 1728 const VkPhysicalDeviceSampleLocationsPropertiesEXT m_sampleLocationsProperties; 1729 const VkFormat m_colorFormat; 1730 UVec2 m_renderSize; 1731 MovePtr<MultisamplePixelGrid> m_pixelGrid; 1732 deUint32 m_numVertices; 1733 Move<VkBuffer> m_vertexBuffer; 1734 MovePtr<Allocation> m_vertexBufferAlloc; 1735 Move<VkImage> m_colorImage; 1736 Move<VkImageView> m_colorImageView; 1737 MovePtr<Allocation> m_colorImageAlloc; 1738 Move<VkImage> m_resolveImage; 1739 Move<VkImageView> m_resolveImageView; 1740 MovePtr<Allocation> m_resolveImageAlloc; 1741 Move<VkBuffer> m_colorBuffer; 1742 MovePtr<Allocation> m_colorBufferAlloc; 1743 Move<VkBuffer> m_sampleDataBuffer; 1744 MovePtr<Allocation> m_sampleDataBufferAlloc; 1745 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 1746 Move<VkDescriptorPool> m_descriptorPool; 1747 Move<VkDescriptorSet> m_descriptorSet; 1748 1749private: 1750 deUint32 m_currentGridNdx; 1751 std::vector<UVec2> m_gridSizes; 1752}; 1753 1754//! Check that each custom sample has the expected position 1755class VerifyLocationTest : public TestBase 1756{ 1757public: 1758 VerifyLocationTest (Context& context, const TestParams params) : TestBase(context, params) {} 1759 1760 bool testPixelGrid (void) 1761 { 1762 // Create vertices 1763 { 1764 // For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it. 1765 // NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution. 1766 const Vec2 pixelSize = Vec2(2.0f) / m_renderSize.cast<float>(); 1767 const Vec2 offset = pixelSize / UVec2(1u << m_sampleLocationsProperties.sampleLocationSubPixelBits).cast<float>(); 1768 std::vector<Vec4> vertices; 1769 1770 // Surround with a roughly centered triangle 1771 const float y1 = 0.5f * offset.y(); 1772 const float y2 = 0.35f * offset.y(); 1773 const float x1 = 0.5f * offset.x(); 1774 1775 const std::vector<Vec2> locations = genFramebufferSampleLocations(*m_pixelGrid, m_pixelGrid->size(), m_renderSize); 1776 for (std::vector<Vec2>::const_iterator iter = locations.begin(); iter != locations.end(); ++iter) 1777 { 1778 vertices.push_back(Vec4(iter->x(), iter->y() - y1, 0.0f, 1.0f)); 1779 vertices.push_back(Vec4(iter->x() - x1, iter->y() + y2, 0.0f, 1.0f)); 1780 vertices.push_back(Vec4(iter->x() + x1, iter->y() + y2, 0.0f, 1.0f)); 1781 } 1782 1783 createVertexBuffer(vertices); 1784 } 1785 1786 createSampleDataBufferAndDescriptors(SampleDataSSBO::STATIC_SIZE); // no per-sample data used 1787 1788 drawSinglePass(VERTEX_INPUT_VEC4); // sample locations are taken from the pixel grid 1789 1790 // Verify 1791 1792 const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr())); 1793 1794 return compareGreenImage(m_context.getTestContext().getLog(), "resolve0", "Resolved test image", image); 1795 } 1796}; 1797 1798//! Verify that vertex attributes are correctly interpolated at each custom sample location 1799class VerifyInterpolationTest : public TestBase 1800{ 1801public: 1802 VerifyInterpolationTest (Context& context, const TestParams params) : TestBase(context, params) {} 1803 1804 bool testPixelGrid (void) 1805 { 1806 createVertexBuffer(genVerticesFullQuad()); 1807 1808 // Create sample data SSBO 1809 { 1810 const deUint32 numSamples = m_pixelGrid->samplesPerPixel(); 1811 const deUint32 numDataEntries = numSamples * m_renderSize.x() * m_renderSize.y(); 1812 const VkDeviceSize bufferSize = SampleDataSSBO::STATIC_SIZE + sizeof(Vec2) * numDataEntries; 1813 1814 createSampleDataBufferAndDescriptors(bufferSize); 1815 1816 Vec2* const pSampleData = SampleDataSSBO::sampleData<Vec2>(m_sampleDataBufferAlloc->getHostPtr()); 1817 const std::vector<Vec2> locations = genFramebufferSampleLocations(*m_pixelGrid, m_pixelGrid->size(), m_renderSize); 1818 1819 // Fill SSBO with interpolated values (here: from -1.0 to 1.0 across the render area in both x and y) 1820 DE_ASSERT(locations.size() == numDataEntries); 1821 std::copy(locations.begin(), locations.end(), pSampleData); 1822 1823 flushAlloc(m_context.getDeviceInterface(), m_context.getDevice(), *m_sampleDataBufferAlloc); 1824 } 1825 1826 drawSinglePass(VERTEX_INPUT_VEC4_VEC4); // sample locations are taken from the pixel grid 1827 1828 // Verify 1829 1830 const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr())); 1831 1832 return compareGreenImage(m_context.getTestContext().getLog(), "resolve0", "Resolved test image", image); 1833 } 1834}; 1835 1836template<typename Test, typename ProgramsFunc> 1837void addCases (tcu::TestCaseGroup* group, const VkSampleCountFlagBits numSamples, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate, const ProgramsFunc initPrograms) 1838{ 1839 TestParams params; 1840 deMemset(¶ms, 0, sizeof(params)); 1841 1842 params.pipelineConstructionType = pipelineConstructionType; 1843 params.numSamples = numSamples; 1844 1845 struct TestOptions 1846 { 1847 std::string testSuffix; 1848 TestOptionFlags testFlags; 1849 1850 }; 1851 1852 TestOptions testOpts[] = 1853 { 1854 { "", useFragmentShadingRate ? (TestOptionFlags)TEST_OPTION_FRAGMENT_SHADING_RATE_BIT : (TestOptionFlags)0 | (TestOptionFlags)TEST_OPTION_VARIABLE_SAMPLE_LOCATIONS_BIT }, 1855 { "_invariable", useFragmentShadingRate ? (TestOptionFlags)TEST_OPTION_FRAGMENT_SHADING_RATE_BIT : (TestOptionFlags)0 } 1856 }; 1857 1858 for (const auto &options : testOpts) 1859 { 1860 params.options = options.testFlags; 1861 1862 addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + options.testSuffix).c_str(), checkSupportVerifyTests, initPrograms, params); 1863 1864 params.options |= (TestOptionFlags)TEST_OPTION_DYNAMIC_STATE_BIT; 1865 addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + "_dynamic" + options.testSuffix).c_str(), checkSupportVerifyTests, initPrograms, params); 1866 1867 params.options |= (TestOptionFlags)TEST_OPTION_CLOSELY_PACKED_BIT; 1868 addInstanceTestCaseWithPrograms<Test>(group, (getString(numSamples) + "_packed" + options.testSuffix).c_str(), checkSupportVerifyTests, initPrograms, params); 1869 } 1870} 1871 1872} // VerifySamples 1873 1874// Draw tests with at least two "passes" where sample locations may change. 1875// Test case is based on a combination of parameters defined below. Not all combinations are compatible. 1876namespace Draw 1877{ 1878 1879//! Options common to all test cases 1880enum TestOptionFlagBits 1881{ 1882 TEST_OPTION_SAME_PATTERN_BIT = 1u << 0, //!< Use the same sample pattern for all operations 1883 TEST_OPTION_DYNAMIC_STATE_BIT = 1u << 1, //!< Use dynamic pipeline state to pass in sample locations 1884 TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT = 1u << 2, //!< Put drawing commands in a secondary buffer, including sample locations change (if dynamic) 1885 TEST_OPTION_GENERAL_LAYOUT_BIT = 1u << 3, //!< Transition the image to general layout at some point in rendering 1886 TEST_OPTION_WAIT_EVENTS_BIT = 1u << 4, //!< Use image memory barriers with vkCmdWaitEvents rather than vkCmdPipelineBarrier 1887 TEST_OPTION_FRAGMENT_SHADING_RATE_BIT = 1u << 5, //!< Use VK_KHR_fragment_shading_rate 1888}; 1889typedef deUint32 TestOptionFlags; 1890 1891//! Determines where draws/clears with custom samples occur in the test 1892enum TestDrawIn 1893{ 1894 TEST_DRAW_IN_RENDER_PASSES = 0u, //!< Each operation in a separate render pass 1895 TEST_DRAW_IN_SUBPASSES, //!< Each operation in a separate subpass of the same render pass 1896 TEST_DRAW_IN_SAME_SUBPASS, //!< Each operation in the same subpass 1897}; 1898 1899//! How a clear before the second pass will be done 1900enum TestClears 1901{ 1902 TEST_CLEARS_NO_CLEAR = 0u, //!< Don't clear 1903 TEST_CLEARS_LOAD_OP_CLEAR, //!< Render pass attachment load clear 1904 TEST_CLEARS_CMD_CLEAR_ATTACHMENTS, //!< vkCmdClearAttachments within a subpass 1905 TEST_CLEARS_CMD_CLEAR_IMAGE, //!< vkCmdClear{Color|DepthStencil}Image outside a render pass 1906}; 1907 1908//! What type of image will be verified with custom samples 1909enum TestImageAspect 1910{ 1911 TEST_IMAGE_ASPECT_COLOR = 0u, //!< Color image 1912 TEST_IMAGE_ASPECT_DEPTH, //!< Depth aspect of an image (can be mixed format) 1913 TEST_IMAGE_ASPECT_STENCIL, //!< Stencil aspect of an image (can be mixed format) 1914}; 1915 1916struct TestParams 1917{ 1918 PipelineConstructionType pipelineConstructionType; 1919 VkSampleCountFlagBits numSamples; 1920 TestOptionFlags options; 1921 TestDrawIn drawIn; 1922 TestClears clears; 1923 TestImageAspect imageAspect; 1924}; 1925 1926void checkSupportDrawTests (Context& context, const TestParams params) 1927{ 1928 checkSupportSampleLocations(context); 1929 1930 if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & params.numSamples) == 0u) 1931 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported"); 1932 1933 if ((getSampleLocationsPropertiesEXT(context).sampleLocationSampleCounts & params.numSamples) == 0u) 1934 TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: sample count not supported"); 1935 1936 // Are we allowed to modify the sample pattern within the same subpass? 1937 if (params.drawIn == TEST_DRAW_IN_SAME_SUBPASS && ((params.options & TEST_OPTION_SAME_PATTERN_BIT) == 0) && !getSampleLocationsPropertiesEXT(context).variableSampleLocations) 1938 TCU_THROW(NotSupportedError, "VkPhysicalDeviceSampleLocationsPropertiesEXT: variableSampleLocations not supported"); 1939 1940 if (TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & params.options) 1941 checkFragmentShadingRateRequirements(context, params.numSamples); 1942 1943 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType); 1944 1945#ifndef CTS_USES_VULKANSC 1946 if (TEST_OPTION_WAIT_EVENTS_BIT & params.options && 1947 context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events) 1948 { 1949 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation"); 1950 } 1951#endif // CTS_USES_VULKANSC 1952} 1953 1954const char* getString (const TestImageAspect aspect) 1955{ 1956 switch (aspect) 1957 { 1958 case TEST_IMAGE_ASPECT_COLOR: return "color"; 1959 case TEST_IMAGE_ASPECT_DEPTH: return "depth"; 1960 case TEST_IMAGE_ASPECT_STENCIL: return "stencil"; 1961 } 1962 DE_ASSERT(0); 1963 return DE_NULL; 1964} 1965 1966const char* getString (const TestDrawIn drawIn) 1967{ 1968 switch (drawIn) 1969 { 1970 case TEST_DRAW_IN_RENDER_PASSES: return "separate_renderpass"; 1971 case TEST_DRAW_IN_SUBPASSES: return "separate_subpass"; 1972 case TEST_DRAW_IN_SAME_SUBPASS: return "same_subpass"; 1973 } 1974 DE_ASSERT(0); 1975 return DE_NULL; 1976} 1977 1978const char* getString (const TestClears clears) 1979{ 1980 switch (clears) 1981 { 1982 case TEST_CLEARS_NO_CLEAR: return "no_clear"; 1983 case TEST_CLEARS_LOAD_OP_CLEAR: return "load_op_clear"; 1984 case TEST_CLEARS_CMD_CLEAR_ATTACHMENTS: return "clear_attachments"; 1985 case TEST_CLEARS_CMD_CLEAR_IMAGE: return "clear_image"; 1986 } 1987 DE_ASSERT(0); 1988 return DE_NULL; 1989} 1990 1991std::string getTestOptionFlagsString (const deUint32 flags) 1992{ 1993 std::ostringstream str; 1994 1995 if ((flags & TEST_OPTION_SAME_PATTERN_BIT) != 0) str << (str.tellp() > 0 ? "_" : "") << "same_pattern"; 1996 if ((flags & TEST_OPTION_DYNAMIC_STATE_BIT) != 0) str << (str.tellp() > 0 ? "_" : "") << "dynamic"; 1997 if ((flags & TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT) != 0) str << (str.tellp() > 0 ? "_" : "") << "secondary_cmd_buf"; 1998 if ((flags & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0) str << (str.tellp() > 0 ? "_" : "") << "general_layout"; 1999 if ((flags & TEST_OPTION_WAIT_EVENTS_BIT) != 0) str << (str.tellp() > 0 ? "_" : "") << "event"; 2000 2001 return str.str(); 2002} 2003 2004void initPrograms (SourceCollections& programCollection, const TestParams) 2005{ 2006 // Vertex shader 2007 { 2008 std::ostringstream src; 2009 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 2010 << "\n" 2011 << "layout(location = 0) in vec4 in_position;\n" 2012 << "layout(location = 1) in vec4 in_color;\n" 2013 << "layout(location = 0) out vec4 o_color;\n" 2014 << "\n" 2015 << "out gl_PerVertex {\n" 2016 << " vec4 gl_Position;\n" 2017 << "};\n" 2018 << "\n" 2019 << "void main(void)\n" 2020 << "{\n" 2021 << " gl_Position = in_position;\n" 2022 << " o_color = in_color;\n" 2023 << "\n" 2024 // We use instance index to draw the left shape (index = 0) or the right shape (index = 1). 2025 // Vertices are squished and moved to either half of the viewport. 2026 << " if (gl_InstanceIndex == 0)\n" 2027 << " gl_Position.x = 0.5 * (gl_Position.x - 1.0);\n" 2028 << " else if (gl_InstanceIndex == 1)\n" 2029 << " gl_Position.x = 0.5 * (gl_Position.x + 1.0);\n" 2030 << "}\n"; 2031 2032 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 2033 } 2034 2035 // Fragment shader 2036 { 2037 std::ostringstream src; 2038 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 2039 << "\n" 2040 << "layout(location = 0) in vec4 in_color;\n" 2041 << "layout(location = 0) out vec4 o_color;\n" 2042 << "\n" 2043 << "void main(void)\n" 2044 << "{\n" 2045 << " o_color = in_color;\n" 2046 << "}\n"; 2047 2048 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 2049 } 2050} 2051 2052//! Draw shapes using changing sample patterns. Add clears and other operations as necessary 2053class DrawTest : public TestInstance 2054{ 2055 static const deUint32 NUM_PASSES = 2u; 2056 2057public: 2058 DrawTest (Context& context, const TestParams params) 2059 : TestInstance (context) 2060 , m_params (params) 2061 , m_sampleLocationsProperties (getSampleLocationsPropertiesEXT(context)) 2062 , m_renderSize (64, 32) 2063 , m_numVertices (0) 2064 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 2065 , m_depthStencilFormat (VK_FORMAT_UNDEFINED) 2066 , m_depthStencilAspect (0) 2067 { 2068 VkMultisamplePropertiesEXT multisampleProperties = 2069 { 2070 VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT, // VkStructureType sType; 2071 DE_NULL, // void* pNext; 2072 VkExtent2D(), // VkExtent2D maxSampleLocationGridSize; 2073 }; 2074 2075 // For this test always use the full pixel grid 2076 2077 m_context.getInstanceInterface().getPhysicalDeviceMultisamplePropertiesEXT(m_context.getPhysicalDevice(), m_params.numSamples, &multisampleProperties); 2078 m_gridSize.x() = multisampleProperties.maxSampleLocationGridSize.width; 2079 m_gridSize.y() = multisampleProperties.maxSampleLocationGridSize.height; 2080 } 2081 2082 tcu::TestStatus iterate (void) 2083 { 2084 // Requirements 2085 if (!(m_gridSize.x() >= 1 && m_gridSize.y() >= 1)) 2086 return tcu::TestStatus::fail("maxSampleLocationGridSize is invalid"); 2087 2088 // Images 2089 { 2090 const DeviceInterface& vk = m_context.getDeviceInterface(); 2091 const VkDevice device = m_context.getDevice(); 2092 Allocator& allocator = m_context.getDefaultAllocator(); 2093 const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 2094 2095 m_colorImage = makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, m_params.numSamples, colorImageUsageFlags); 2096 m_colorImageAlloc = bindImage(vk, device, allocator, *m_colorImage, MemoryRequirement::Any); 2097 m_colorImageView = makeImageView(vk, device, *m_colorImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, 2098 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 2099 2100 m_resolveImage = makeImage(vk, device, (VkImageCreateFlags)0, m_colorFormat, m_renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags); 2101 m_resolveImageAlloc = bindImage(vk, device, allocator, *m_resolveImage, MemoryRequirement::Any); 2102 m_resolveImageView = makeImageView(vk, device, *m_resolveImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, 2103 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 2104 2105 const VkDeviceSize colorBufferSize = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(m_colorFormat)); 2106 m_colorBuffer = makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 2107 m_colorBufferAlloc = bindBuffer(vk, device, allocator, *m_colorBuffer, MemoryRequirement::HostVisible); 2108 2109 if (m_params.imageAspect != TEST_IMAGE_ASPECT_COLOR) 2110 { 2111 const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 2112 2113 m_depthStencilFormat = findSupportedDepthStencilFormat(m_context, useDepth(), useStencil()); 2114 m_depthStencilAspect = (useDepth() ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0) | 2115 (useStencil() ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0); 2116 m_depthStencilImage = makeImage(vk, device, VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT, 2117 m_depthStencilFormat, m_renderSize, m_params.numSamples, depthStencilImageUsageFlags); 2118 m_depthStencilImageAlloc = bindImage(vk, device, allocator, *m_depthStencilImage, MemoryRequirement::Any); 2119 m_depthStencilImageView = makeImageView(vk, device, *m_depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, m_depthStencilFormat, 2120 makeImageSubresourceRange(m_depthStencilAspect, 0u, 1u, 0u, 1u)); 2121 } 2122 } 2123 2124 // Vertices 2125 { 2126 const DeviceInterface& vk = m_context.getDeviceInterface(); 2127 const VkDevice device = m_context.getDevice(); 2128 Allocator& allocator = m_context.getDefaultAllocator(); 2129 2130 std::vector<PositionColor> vertices; 2131 2132 if (useDepth()) 2133 { 2134 append(vertices, genVerticesShapes (RGBA::black().toVec(), DEPTH_REFERENCE / 2.0f)); // mask above (z = 0.0 is nearest) 2135 append(vertices, genVerticesFullQuad(RGBA::white().toVec(), DEPTH_REFERENCE)); // fill below the mask, using the depth test 2136 } 2137 else if (useStencil()) 2138 { 2139 append(vertices, genVerticesShapes (RGBA::black().toVec(), DEPTH_REFERENCE)); // first mask 2140 append(vertices, genVerticesFullQuad(RGBA::white().toVec(), DEPTH_REFERENCE / 2.0f)); // then fill the whole area, using the stencil test 2141 } 2142 else 2143 vertices = genVerticesShapes(); 2144 2145 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(vertices.size() * sizeof(vertices[0])); 2146 2147 m_numVertices = static_cast<deUint32>(vertices.size()); 2148 m_vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 2149 m_vertexBufferAlloc = bindBuffer(vk, device, allocator, *m_vertexBuffer, MemoryRequirement::HostVisible); 2150 2151 deMemcpy(m_vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize)); 2152 flushAlloc(vk, device, *m_vertexBufferAlloc); 2153 } 2154 2155 // Multisample pixel grids - set up two sample patterns for two draw passes 2156 { 2157 const deUint32 numGrids = (useSameSamplePattern() ? 1u : NUM_PASSES); 2158 m_pixelGrids.reserve(numGrids); 2159 2160 for (deUint32 passNdx = 0u; passNdx < numGrids; ++passNdx) 2161 { 2162 const deUint32 seed = 142u + 75u * passNdx; 2163 m_pixelGrids.push_back(MultisamplePixelGrid(m_gridSize, m_params.numSamples)); 2164 fillSampleLocationsRandom(m_pixelGrids.back(), m_sampleLocationsProperties.sampleLocationSubPixelBits, seed); 2165 logPixelGrid (m_context.getTestContext().getLog(), m_sampleLocationsProperties, m_pixelGrids.back()); 2166 } 2167 } 2168 2169 // Some test cases will not clear the left hand image, so we can use it directly 2170 const bool isClearCase = (m_params.clears != TEST_CLEARS_NO_CLEAR); 2171 const bool hasLeftSideImage = (!isClearCase || 2172 (m_params.drawIn != TEST_DRAW_IN_RENDER_PASSES && m_params.clears != TEST_CLEARS_CMD_CLEAR_ATTACHMENTS)); 2173 2174 // Render second pass reference image with the first pattern 2175 tcu::TextureLevel refImagePattern0; 2176 if (!useSameSamplePattern() && !hasLeftSideImage) 2177 { 2178 const tcu::TextureFormat colorFormat = mapVkFormat(m_colorFormat); 2179 2180 drawPatternChangeReference(); 2181 2182 refImagePattern0.setStorage(colorFormat, m_renderSize.x(), m_renderSize.y()); 2183 tcu::copy(refImagePattern0.getAccess(), tcu::ConstPixelBufferAccess(colorFormat, tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr())); 2184 } 2185 2186 // Two-pass rendering 2187 2188 switch (m_params.drawIn) 2189 { 2190 case TEST_DRAW_IN_RENDER_PASSES: drawRenderPasses(); break; 2191 case TEST_DRAW_IN_SUBPASSES: drawSubpasses(); break; 2192 case TEST_DRAW_IN_SAME_SUBPASS: drawSameSubpass(); break; 2193 2194 default: 2195 DE_ASSERT(0); 2196 break; 2197 } 2198 2199 // Log the result 2200 2201 const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(m_colorFormat), tcu::IVec3(m_renderSize.x(), m_renderSize.y(), 1), m_colorBufferAlloc->getHostPtr())); 2202 2203 m_context.getTestContext().getLog() 2204 << tcu::TestLog::ImageSet("Result", "Final result") 2205 << tcu::TestLog::Image("resolve0", "resolve0", image) 2206 << tcu::TestLog::EndImageSet; 2207 2208 // Verify result 2209 { 2210 DE_ASSERT((m_renderSize.x() % 2) == 0); 2211 DE_ASSERT((m_renderSize.y() % 2) == 0); 2212 2213 // Count colors in each image half separately, each half may have its own background color 2214 const int numBackgroundColors = 1; 2215 const int numExpectedColorsRight = numBackgroundColors + static_cast<int>(m_params.numSamples); 2216 const int numExpectedColorsLeft = (isClearCase ? numBackgroundColors : numExpectedColorsRight); 2217 const int numActualColorsLeft = countUniqueColors(tcu::getSubregion(image, 0, 0, m_renderSize.x()/2, m_renderSize.y())); 2218 const int numActualColorsRight = countUniqueColors(tcu::getSubregion(image, m_renderSize.x()/2, 0, m_renderSize.x()/2, m_renderSize.y())); 2219 2220 if (numActualColorsLeft != numExpectedColorsLeft || numActualColorsRight != numExpectedColorsRight) 2221 { 2222 std::ostringstream msg; 2223 msg << "Expected " << numExpectedColorsLeft << " unique colors, but got " << numActualColorsLeft; 2224 2225 if (numActualColorsLeft != numActualColorsRight) 2226 msg << " and " << numActualColorsRight; 2227 2228 m_context.getTestContext().getLog() 2229 << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage; 2230 2231 return tcu::TestStatus::fail("Resolved image has incorrect pixels"); 2232 } 2233 2234 if (hasLeftSideImage) 2235 { 2236 // Compare the left and the right half 2237 const bool match = intThresholdCompare(tcu::getSubregion(image, 0, 0, m_renderSize.x()/2, m_renderSize.y()), 2238 tcu::getSubregion(image, m_renderSize.x()/2, 0, m_renderSize.x()/2, m_renderSize.y()), 2239 UVec4(2u)); 2240 if (useSameSamplePattern() && !match) 2241 return tcu::TestStatus::fail("Multisample pattern should be identical in both image halves"); 2242 else if (!useSameSamplePattern() && match) 2243 return tcu::TestStatus::fail("Multisample pattern doesn't seem to change between left and right image halves"); 2244 } 2245 else if (!useSameSamplePattern()) 2246 { 2247 // Compare the right half with the previously rendered reference image -- patterns should be different 2248 bool match = intThresholdCompare(tcu::getSubregion(refImagePattern0.getAccess(), m_renderSize.x()/2, 0, m_renderSize.x()/2, m_renderSize.y()), 2249 tcu::getSubregion(image, m_renderSize.x()/2, 0, m_renderSize.x()/2, m_renderSize.y()), 2250 UVec4(2u)); 2251 2252 if (match) 2253 return tcu::TestStatus::fail("Multisample pattern doesn't seem to change between passes"); 2254 } 2255 } 2256 2257 return tcu::TestStatus::pass("Pass"); 2258 } 2259 2260protected: 2261 bool useDepth (void) const { return m_params.imageAspect == TEST_IMAGE_ASPECT_DEPTH; } 2262 bool useStencil (void) const { return m_params.imageAspect == TEST_IMAGE_ASPECT_STENCIL; } 2263 bool useSameSamplePattern (void) const { return (m_params.options & TEST_OPTION_SAME_PATTERN_BIT) != 0u; } 2264 bool useDynamicState (void) const { return (m_params.options & TEST_OPTION_DYNAMIC_STATE_BIT) != 0u; } 2265 bool useSecondaryCmdBuffer (void) const { return (m_params.options & TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT) != 0u; } 2266 bool useGeneralLayout (void) const { return (m_params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0u; } 2267 bool useWaitEvents (void) const { return (m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) != 0u; } 2268 bool useFragmentShadingRate (void) const { return (m_params.options & TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) != 0u; } 2269 2270 //! Draw the second pass image, but with sample pattern from the first pass -- used to verify that the pattern is different 2271 void drawPatternChangeReference (void) 2272 { 2273 const InstanceInterface& vki = m_context.getInstanceInterface(); 2274 const DeviceInterface& vk = m_context.getDeviceInterface(); 2275 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 2276 const VkDevice device = m_context.getDevice(); 2277 const VkViewport viewport = makeViewport(m_renderSize); 2278 const VkRect2D renderArea = makeRect2D(m_renderSize); 2279 const VkRect2D scissor = makeRect2D(m_renderSize); 2280 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 2281 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 2282 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vk, device); 2283 const VkSampleLocationsInfoEXT sampleLocationsInfo = makeSampleLocationsInfo(m_pixelGrids[0]); 2284 const VkClearValue clearColor0 = (m_params.clears == TEST_CLEARS_NO_CLEAR ? makeClearValueColor(CLEAR_COLOR_0) : makeClearValueColor(CLEAR_COLOR_1)); 2285 2286 RenderTarget rt; 2287 2288 rt.addAttachment( 2289 *m_colorImage, // VkImage image 2290 *m_colorImageView, // VkImageView imageView, 2291 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2292 m_colorFormat, // VkFormat format, 2293 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2294 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2295 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2296 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2297 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2298 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2299 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2300 clearColor0); // VkClearValue clearValue, 2301 2302 rt.addAttachment( 2303 *m_resolveImage, // VkImage image 2304 *m_resolveImageView, // VkImageView imageView, 2305 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2306 m_colorFormat, // VkFormat format, 2307 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits numSamples, 2308 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp, 2309 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2310 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2311 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2312 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2313 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout finalLayout, 2314 VkClearValue()); // VkClearValue clearValue, 2315 2316 rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 2317 1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 2318 2319 if (useDepth() || useStencil()) 2320 { 2321 rt.addAttachment( 2322 *m_depthStencilImage, // VkImage image 2323 *m_depthStencilImageView, // VkImageView imageView, 2324 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2325 m_depthStencilFormat, // VkFormat format, 2326 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2327 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2328 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2329 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp, 2330 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp, 2331 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2332 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2333 makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE), // VkClearValue clearValue, 2334 &sampleLocationsInfo); // VkSampleLocationsInfoEXT* pInitialSampleLocations 2335 2336 rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo); 2337 } 2338 2339 rt.bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 2340 2341 GraphicsPipelineWrapper pipeline(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2342 preparePipelineWrapper(pipeline, std::vector<VkDynamicState>(), pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, 2343 /*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo, 2344 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate()); 2345 2346 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex())); 2347 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 2348 Move<VkCommandBuffer> secondaryCmdBuffer; 2349 VkCommandBuffer currentCmdBuffer = *cmdBuffer; 2350 2351 beginCommandBuffer(vk, currentCmdBuffer); 2352 rt.recordBeginRenderPass(vk, currentCmdBuffer, renderArea, (useSecondaryCmdBuffer() ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE)); 2353 2354 // For maximum consistency also use a secondary command buffer, if the two-pass path uses it 2355 if (useSecondaryCmdBuffer()) 2356 { 2357 secondaryCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 2358 currentCmdBuffer = *secondaryCmdBuffer; 2359 2360 beginSecondaryCommandBuffer(vk, currentCmdBuffer, rt.getRenderPassWrapper(), /*subpass*/ 0u, m_params.numSamples, m_params.pipelineConstructionType); 2361 } 2362 2363 vk.cmdBindVertexBuffers(currentCmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO); 2364 pipeline.bind(currentCmdBuffer); 2365 2366 // Draw the right shape only 2367 vk.cmdDraw(currentCmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 1u); 2368 2369 if (useSecondaryCmdBuffer()) 2370 { 2371 endCommandBuffer(vk, currentCmdBuffer); 2372 currentCmdBuffer = *cmdBuffer; 2373 2374 vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer.get()); 2375 } 2376 2377 rt.endRenderPass(vk, *cmdBuffer); 2378 2379 recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer); 2380 2381 endCommandBuffer(vk, *cmdBuffer); 2382 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer); 2383 2384 invalidateAlloc(vk, device, *m_colorBufferAlloc); 2385 } 2386 2387 //! Draw two shapes with distinct sample patterns, each in its own render pass 2388 void drawRenderPasses (void) 2389 { 2390 const InstanceInterface& vki = m_context.getInstanceInterface(); 2391 const DeviceInterface& vk = m_context.getDeviceInterface(); 2392 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 2393 const VkDevice device = m_context.getDevice(); 2394 const VkViewport viewport = makeViewport(m_renderSize); 2395 const VkRect2D renderArea = makeRect2D(m_renderSize); 2396 const VkRect2D scissor = makeRect2D(m_renderSize); 2397 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 2398 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 2399 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vk, device); 2400 const VkClearValue clearColor0 = makeClearValueColor(CLEAR_COLOR_0); 2401 const VkClearValue clearColor1 = makeClearValueColor(CLEAR_COLOR_1); 2402 const VkClearValue clearDepthStencil0 = makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE); 2403 const VkSampleLocationsInfoEXT sampleLocationsInfo [NUM_PASSES] = 2404 { 2405 makeSampleLocationsInfo(m_pixelGrids[0]), 2406 makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]), 2407 }; 2408 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex())); 2409 Move<VkCommandBuffer> cmdBuffer [NUM_PASSES] = 2410 { 2411 makeCommandBuffer(vk, device, *cmdPool), 2412 makeCommandBuffer(vk, device, *cmdPool), 2413 }; 2414 Move<VkCommandBuffer> secondaryCmdBuffer [NUM_PASSES]; 2415 RenderTarget rt [NUM_PASSES]; 2416 std::vector<GraphicsPipelineWrapper> pipelines; 2417 Move<VkEvent> event [2]; /*color and depth/stencil*/ 2418 2419 // Layouts expected by the second render pass 2420 const VkImageLayout colorLayout1 = useGeneralLayout() && !(useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 2421 const VkImageLayout depthStencilLayout1 = useGeneralLayout() && (useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 2422 2423 // First render pass - no resolves 2424 { 2425 rt[0].addAttachment( 2426 *m_colorImage, // VkImage image 2427 *m_colorImageView, // VkImageView imageView, 2428 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2429 m_colorFormat, // VkFormat format, 2430 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2431 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2432 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2433 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2434 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2435 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2436 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2437 clearColor0); // VkClearValue clearValue, 2438 2439 rt[0].addSubpassColorAttachment(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 2440 2441 if (useDepth() || useStencil()) 2442 { 2443 rt[0].addAttachment( 2444 *m_depthStencilImage, // VkImage image 2445 *m_depthStencilImageView, // VkImageView imageView, 2446 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2447 m_depthStencilFormat, // VkFormat format, 2448 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2449 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2450 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2451 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp, 2452 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp, 2453 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2454 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2455 clearDepthStencil0, // VkClearValue clearValue, 2456 &sampleLocationsInfo[0]); // VkSampleLocationsInfoEXT* pInitialSampleLocations 2457 2458 rt[0].addSubpassDepthStencilAttachment(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]); 2459 } 2460 2461 rt[0].bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 2462 } 2463 2464 // Second render pass 2465 { 2466 const VkAttachmentLoadOp loadOp = (m_params.clears == TEST_CLEARS_LOAD_OP_CLEAR ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD); 2467 2468 rt[1].addAttachment( 2469 *m_colorImage, // VkImage image 2470 *m_colorImageView, // VkImageView imageView, 2471 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2472 m_colorFormat, // VkFormat format, 2473 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2474 loadOp, // VkAttachmentLoadOp loadOp, 2475 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2476 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2477 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2478 colorLayout1, // VkImageLayout initialLayout, 2479 colorLayout1, // VkImageLayout finalLayout, 2480 clearColor1); // VkClearValue clearValue, 2481 2482 rt[1].addAttachment( 2483 *m_resolveImage, // VkImage image 2484 *m_resolveImageView, // VkImageView imageView, 2485 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2486 m_colorFormat, // VkFormat format, 2487 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits numSamples, 2488 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp, 2489 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2490 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2491 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2492 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2493 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout finalLayout, 2494 VkClearValue()); // VkClearValue clearValue, 2495 2496 rt[1].addSubpassColorAttachmentWithResolve(0u, colorLayout1, 2497 1u, colorLayout1); 2498 2499 if (useDepth() || useStencil()) 2500 { 2501 rt[1].addAttachment( 2502 *m_depthStencilImage, // VkImage image 2503 *m_depthStencilImageView, // VkImageView imageView, 2504 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2505 m_depthStencilFormat, // VkFormat format, 2506 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2507 loadOp, // VkAttachmentLoadOp loadOp, 2508 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2509 loadOp, // VkAttachmentLoadOp stencilLoadOp, 2510 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp, 2511 depthStencilLayout1, // VkImageLayout initialLayout, 2512 depthStencilLayout1, // VkImageLayout finalLayout, 2513 clearDepthStencil0, // VkClearValue clearValue, 2514 &sampleLocationsInfo[1]); // VkSampleLocationsInfoEXT* pInitialSampleLocations 2515 2516 rt[1].addSubpassDepthStencilAttachment(2u, depthStencilLayout1, &sampleLocationsInfo[1]); 2517 } 2518 2519 rt[1].bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 2520 } 2521 2522 // Pipelines 2523 pipelines.reserve(NUM_PASSES); 2524 if (useDynamicState()) 2525 { 2526 std::vector<VkDynamicState> dynamicState; 2527 dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT); 2528 2529 for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 2530 { 2531 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2532 preparePipelineWrapper(pipelines.back(), dynamicState, pipelineLayout, rt[passNdx].getRenderPass(), vertexModule, fragmentModule, 2533 /*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(), 2534 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate()); 2535 } 2536 } 2537 else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 2538 { 2539 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2540 preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), pipelineLayout, rt[passNdx].getRenderPass(), vertexModule, fragmentModule, 2541 /*subpass index*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx], 2542 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate()); 2543 } 2544 2545 // Record secondary command buffers 2546 2547 if (useSecondaryCmdBuffer()) 2548 { 2549 secondaryCmdBuffer[0] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 2550 secondaryCmdBuffer[1] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 2551 2552 // First render pass contents 2553 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[0], rt[0].getRenderPassWrapper(), /*subpass*/ 0u, m_params.numSamples, m_params.pipelineConstructionType); 2554 recordFirstPassContents(*secondaryCmdBuffer[0], pipelines[0], sampleLocationsInfo[0]); 2555 endCommandBuffer(vk, *secondaryCmdBuffer[0]); 2556 2557 // Second render pass contents 2558 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[1], rt[1].getRenderPassWrapper(), /*subpass*/ 0u, m_params.numSamples, m_params.pipelineConstructionType); 2559 recordSecondPassContents(*secondaryCmdBuffer[1], pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 2560 endCommandBuffer(vk, *secondaryCmdBuffer[1]); 2561 } 2562 2563 // Record primary command buffers 2564 2565 VkCommandBuffer currentCmdBuffer = *cmdBuffer[0]; 2566 beginCommandBuffer(vk, currentCmdBuffer); 2567 2568 // First render pass 2569 if (useSecondaryCmdBuffer()) 2570 { 2571 rt[0].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2572 vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer[0].get()); 2573 rt[0].endRenderPass(vk, currentCmdBuffer); 2574 } 2575 else 2576 { 2577 rt[0].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE); 2578 recordFirstPassContents(currentCmdBuffer, pipelines[0], sampleLocationsInfo[0]); 2579 rt[0].endRenderPass(vk, currentCmdBuffer); 2580 } 2581 2582 endCommandBuffer(vk, currentCmdBuffer); 2583 2584 // Record the second primary command buffer 2585 currentCmdBuffer = *cmdBuffer[1]; 2586 beginCommandBuffer(vk, currentCmdBuffer); 2587 2588 if (m_params.clears == TEST_CLEARS_CMD_CLEAR_IMAGE) 2589 { 2590 { 2591 const VkImageLayout finalLayout = (useWaitEvents() ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : colorLayout1); 2592 2593 recordImageBarrier(vk, currentCmdBuffer, *m_colorImage, 2594 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect, 2595 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask, 2596 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask, 2597 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2598 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask, 2599 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2600 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); // VkImageLayout newLayout) 2601 2602 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 2603 vk.cmdClearColorImage(currentCmdBuffer, *m_colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor1.color, 1u, &subresourceRange); 2604 2605 recordImageBarrier(vk, currentCmdBuffer, *m_colorImage, 2606 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect, 2607 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags srcStageMask, 2608 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask, 2609 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask, 2610 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 2611 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2612 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout, 2613 finalLayout); // VkImageLayout newLayout) 2614 } 2615 2616 if (useDepth() || useStencil()) 2617 { 2618 const VkImageLayout finalLayout = (useWaitEvents() ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : depthStencilLayout1); 2619 2620 recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage, 2621 getImageAspectFlags(m_depthStencilFormat), // VkImageAspectFlags aspect, 2622 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask, 2623 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask, 2624 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2625 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask, 2626 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2627 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout) 2628 &sampleLocationsInfo[0]); // VkSampleLocationsInfoEXT 2629 2630 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(m_depthStencilAspect, 0u, 1u, 0u, 1u); 2631 vk.cmdClearDepthStencilImage(currentCmdBuffer, *m_depthStencilImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDepthStencil0.depthStencil, 1u, &subresourceRange); 2632 2633 recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage, 2634 getImageAspectFlags(m_depthStencilFormat), // VkImageAspectFlags aspect, 2635 VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags srcStageMask, 2636 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask, 2637 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask, 2638 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 2639 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2640 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout, 2641 finalLayout, // VkImageLayout newLayout) 2642 &sampleLocationsInfo[0]); // VkSampleLocationsInfoEXT 2643 } 2644 } 2645 else if (!useWaitEvents()) 2646 { 2647 // Barrier between the render passes 2648 2649 recordImageBarrier(vk, currentCmdBuffer, *m_colorImage, 2650 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect, 2651 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask, 2652 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask, 2653 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2654 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 2655 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2656 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2657 colorLayout1); // VkImageLayout newLayout) 2658 2659 if (useDepth() || useStencil()) 2660 { 2661 recordImageBarrier(vk, currentCmdBuffer, *m_depthStencilImage, 2662 getImageAspectFlags(m_depthStencilFormat), // VkImageAspectFlags aspect, 2663 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask, 2664 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask, 2665 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2666 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 2667 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2668 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2669 depthStencilLayout1); // VkImageLayout newLayout) 2670 } 2671 } 2672 2673 if (useWaitEvents()) 2674 { 2675 // Use events to sync both render passes 2676 event[0] = makeEvent(vk, device); 2677 vk.cmdSetEvent(currentCmdBuffer, *event[0], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); 2678 2679 recordWaitEventWithImage(vk, currentCmdBuffer, *event[0], *m_colorImage, 2680 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect, 2681 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask, 2682 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask, 2683 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2684 (VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 2685 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2686 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2687 colorLayout1); // VkImageLayout newLayout, 2688 2689 if (useDepth() || useStencil()) 2690 { 2691 event[1] = makeEvent(vk, device); 2692 vk.cmdSetEvent(currentCmdBuffer, *event[1], VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); 2693 2694 recordWaitEventWithImage(vk, currentCmdBuffer, *event[1], *m_depthStencilImage, 2695 getImageAspectFlags(m_depthStencilFormat), // VkImageAspectFlags aspect, 2696 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask, 2697 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags dstStageMask, 2698 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, 2699 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 2700 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT), // VkAccessFlags dstAccessMask, 2701 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, 2702 depthStencilLayout1); // VkImageLayout newLayout, 2703 } 2704 } 2705 2706 // Second render pass 2707 if (useSecondaryCmdBuffer()) 2708 { 2709 rt[1].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2710 vk.cmdExecuteCommands(currentCmdBuffer, 1u, &secondaryCmdBuffer[1].get()); 2711 rt[1].endRenderPass(vk, currentCmdBuffer); 2712 } 2713 else 2714 { 2715 rt[1].recordBeginRenderPass(vk, currentCmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE); 2716 recordSecondPassContents(currentCmdBuffer, pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 2717 rt[1].endRenderPass(vk, currentCmdBuffer); 2718 } 2719 2720 // Resolve image -> host buffer 2721 recordCopyImageToBuffer(vk, currentCmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer); 2722 2723 endCommandBuffer(vk, currentCmdBuffer); 2724 2725 // Submit work 2726 { 2727 const Unique<VkFence> fence (createFence(vk, device)); 2728 const VkCommandBuffer buffers [NUM_PASSES] = 2729 { 2730 *cmdBuffer[0], 2731 *cmdBuffer[1], 2732 }; 2733 2734 const VkSubmitInfo submitInfo = 2735 { 2736 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 2737 DE_NULL, // const void* pNext; 2738 0u, // uint32_t waitSemaphoreCount; 2739 DE_NULL, // const VkSemaphore* pWaitSemaphores; 2740 DE_NULL, // const VkPipelineStageFlags* pWaitDstStageMask; 2741 DE_LENGTH_OF_ARRAY(buffers), // uint32_t commandBufferCount; 2742 buffers, // const VkCommandBuffer* pCommandBuffers; 2743 0u, // uint32_t signalSemaphoreCount; 2744 DE_NULL, // const VkSemaphore* pSignalSemaphores; 2745 }; 2746 VK_CHECK(vk.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, *fence)); 2747 VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull)); 2748 } 2749 2750 invalidateAlloc(vk, device, *m_colorBufferAlloc); 2751 } 2752 2753 void recordFirstPassContents (const VkCommandBuffer cmdBuffer, 2754 const GraphicsPipelineWrapper& pipeline, 2755 const VkSampleLocationsInfoEXT& sampleLocationsInfo) 2756 { 2757 const DeviceInterface& vk = m_context.getDeviceInterface(); 2758 2759 vk.cmdBindVertexBuffers(cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO); 2760 pipeline.bind(cmdBuffer); 2761 2762 if (useDynamicState()) 2763 vk.cmdSetSampleLocationsEXT(cmdBuffer, &sampleLocationsInfo); 2764 2765 if (m_params.clears == TEST_CLEARS_NO_CLEAR) 2766 vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 0u); // left shape only 2767 else 2768 vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ NUM_PASSES, /*first vertex*/ 0u, /*first instance*/ 0u); // both shapes 2769 } 2770 2771 void recordSecondPassContents (const VkCommandBuffer cmdBuffer, 2772 const GraphicsPipelineWrapper& pipeline, 2773 const VkSampleLocationsInfoEXT& sampleLocationsInfo, 2774 const VkClearValue& clearColor, 2775 const VkClearValue& clearDepthStencil, 2776 const VkRect2D& clearRect) 2777 { 2778 const DeviceInterface& vk = m_context.getDeviceInterface(); 2779 2780 vk.cmdBindVertexBuffers(cmdBuffer, /*first binding*/ 0u, /*num bindings*/ 1u, &m_vertexBuffer.get(), /*offsets*/ &ZERO); 2781 pipeline.bind(cmdBuffer); 2782 2783 if (m_params.clears == TEST_CLEARS_CMD_CLEAR_ATTACHMENTS) 2784 recordClearAttachments(vk, cmdBuffer, 0u, clearColor, m_depthStencilAspect, clearDepthStencil, clearRect); 2785 2786 if (useDynamicState()) 2787 vk.cmdSetSampleLocationsEXT(cmdBuffer, &sampleLocationsInfo); 2788 2789 // Draw the right shape only 2790 vk.cmdDraw(cmdBuffer, m_numVertices, /*instance count*/ 1u, /*first vertex*/ 0u, /*first instance*/ 1u); 2791 } 2792 2793 //! Draw two shapes in two subpasses of the same render pass 2794 void drawSubpasses (void) 2795 { 2796 DE_ASSERT(m_params.clears != TEST_CLEARS_CMD_CLEAR_IMAGE); // not possible in a render pass 2797 DE_ASSERT(m_params.clears != TEST_CLEARS_LOAD_OP_CLEAR); // can't specify a load op for a subpass 2798 DE_ASSERT((m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) == 0); // can't change layouts inside a subpass 2799 2800 const InstanceInterface& vki = m_context.getInstanceInterface(); 2801 const DeviceInterface& vk = m_context.getDeviceInterface(); 2802 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 2803 const VkDevice device = m_context.getDevice(); 2804 const VkViewport viewport = makeViewport(m_renderSize); 2805 const VkRect2D renderArea = makeRect2D(m_renderSize); 2806 const VkRect2D scissor = makeRect2D(m_renderSize); 2807 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 2808 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 2809 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vk, device); 2810 const VkClearValue clearColor0 = makeClearValueColor(CLEAR_COLOR_0); 2811 const VkClearValue clearColor1 = makeClearValueColor(CLEAR_COLOR_1); 2812 const VkClearValue clearDepthStencil0 = makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE); 2813 const VkSampleLocationsInfoEXT sampleLocationsInfo [NUM_PASSES] = 2814 { 2815 makeSampleLocationsInfo(m_pixelGrids[0]), 2816 makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]), 2817 }; 2818 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex())); 2819 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 2820 Move<VkCommandBuffer> secondaryCmdBuffer [NUM_PASSES]; 2821 RenderTarget rt; 2822 std::vector<GraphicsPipelineWrapper> pipelines; 2823 Move<VkEvent> event; 2824 2825 // Layouts used in the second subpass 2826 const VkImageLayout colorLayout1 = useGeneralLayout() && !(useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 2827 const VkImageLayout depthStencilLayout1 = useGeneralLayout() && (useDepth() || useStencil()) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 2828 2829 // Prepare the render pass 2830 { 2831 rt.addAttachment( 2832 *m_colorImage, // VkImage image 2833 *m_colorImageView, // VkImageView imageView, 2834 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2835 m_colorFormat, // VkFormat format, 2836 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2837 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2838 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2839 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2840 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2841 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2842 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2843 clearColor0); // VkClearValue clearValue, 2844 2845 rt.addAttachment( 2846 *m_resolveImage, // VkImage image 2847 *m_resolveImageView, // VkImageView imageView, 2848 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2849 m_colorFormat, // VkFormat format, 2850 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits numSamples, 2851 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp, 2852 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2853 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 2854 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 2855 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2856 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout finalLayout, 2857 VkClearValue()); // VkClearValue clearValue, 2858 2859 // First subpass 2860 rt.addSubpassColorAttachment(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 2861 2862 if (useDepth() || useStencil()) 2863 { 2864 rt.addAttachment( 2865 *m_depthStencilImage, // VkImage image 2866 *m_depthStencilImageView, // VkImageView imageView, 2867 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 2868 m_depthStencilFormat, // VkFormat format, 2869 m_params.numSamples, // VkSampleCountFlagBits numSamples, 2870 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 2871 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 2872 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp, 2873 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp, 2874 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 2875 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 2876 clearDepthStencil0, // VkClearValue clearValue, 2877 &sampleLocationsInfo[0]); // VkSampleLocationsInfoEXT* pInitialSampleLocations 2878 2879 rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]); 2880 } 2881 2882 // Second subpass 2883 rt.nextSubpass(); 2884 rt.addSubpassColorAttachmentWithResolve(0u, colorLayout1, 2885 1u, colorLayout1); 2886 2887 if (useDepth() || useStencil()) 2888 rt.addSubpassDepthStencilAttachment(2u, depthStencilLayout1, &sampleLocationsInfo[1]); 2889 2890 rt.bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 2891 } 2892 2893 // Pipelines 2894 pipelines.reserve(NUM_PASSES); 2895 if (useDynamicState()) 2896 { 2897 std::vector<VkDynamicState> dynamicState; 2898 dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT); 2899 2900 for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 2901 { 2902 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2903 preparePipelineWrapper(pipelines.back(), dynamicState, pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, 2904 /*subpass*/ passNdx, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(), 2905 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate()); 2906 } 2907 } 2908 else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 2909 { 2910 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2911 preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, 2912 /*subpass*/ passNdx, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx], 2913 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate()); 2914 } 2915 2916 // Record secondary command buffers 2917 2918 if (useSecondaryCmdBuffer()) 2919 { 2920 secondaryCmdBuffer[0] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 2921 secondaryCmdBuffer[1] = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 2922 2923 // First subpass contents 2924 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[0], rt.getRenderPassWrapper(), /*subpass*/ 0u, m_params.numSamples, m_params.pipelineConstructionType); 2925 recordFirstPassContents(*secondaryCmdBuffer[0], pipelines[0], sampleLocationsInfo[0]); 2926 endCommandBuffer(vk, *secondaryCmdBuffer[0]); 2927 2928 // Second subpass contents 2929 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer[1], rt.getRenderPassWrapper(), /*subpass*/ 1u, m_params.numSamples, m_params.pipelineConstructionType); 2930 recordSecondPassContents(*secondaryCmdBuffer[1], pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 2931 endCommandBuffer(vk, *secondaryCmdBuffer[1]); 2932 } 2933 2934 // Record primary command buffer 2935 2936 beginCommandBuffer(vk, *cmdBuffer); 2937 2938 if (useSecondaryCmdBuffer()) 2939 { 2940 rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2941 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer[0].get()); 2942 2943 rt.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 2944 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer[1].get()); 2945 } 2946 else 2947 { 2948 rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE); 2949 recordFirstPassContents(*cmdBuffer, pipelines[0], sampleLocationsInfo[0]); 2950 2951 rt.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 2952 recordSecondPassContents(*cmdBuffer, pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 2953 } 2954 2955 rt.endRenderPass(vk, *cmdBuffer); 2956 2957 // Resolve image -> host buffer 2958 recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer); 2959 2960 endCommandBuffer(vk, *cmdBuffer); 2961 2962 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer); 2963 invalidateAlloc(vk, device, *m_colorBufferAlloc); 2964 } 2965 2966 //! Draw two shapes within the same subpass of a renderpass 2967 void drawSameSubpass (void) 2968 { 2969 DE_ASSERT(m_params.clears != TEST_CLEARS_CMD_CLEAR_IMAGE); // not possible in a render pass 2970 DE_ASSERT(m_params.clears != TEST_CLEARS_LOAD_OP_CLEAR); // can't specify a load op for a subpass 2971 DE_ASSERT((m_params.options & TEST_OPTION_WAIT_EVENTS_BIT) == 0); // can't change layouts inside a subpass 2972 DE_ASSERT((m_params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) == 0); // can't change layouts inside a subpass 2973 2974 const InstanceInterface& vki = m_context.getInstanceInterface(); 2975 const DeviceInterface& vk = m_context.getDeviceInterface(); 2976 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 2977 const VkDevice device = m_context.getDevice(); 2978 const VkViewport viewport = makeViewport(m_renderSize); 2979 const VkRect2D renderArea = makeRect2D(m_renderSize); 2980 const VkRect2D scissor = makeRect2D(m_renderSize); 2981 const ShaderWrapper vertexModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 2982 const ShaderWrapper fragmentModule (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 2983 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vk, device); 2984 const VkClearValue clearColor0 = makeClearValueColor(CLEAR_COLOR_0); 2985 const VkClearValue clearColor1 = makeClearValueColor(CLEAR_COLOR_1); 2986 const VkClearValue clearDepthStencil0 = makeClearValueDepthStencil(DEPTH_CLEAR, STENCIL_REFERENCE); 2987 const VkSampleLocationsInfoEXT sampleLocationsInfo [NUM_PASSES] = 2988 { 2989 makeSampleLocationsInfo(m_pixelGrids[0]), 2990 makeSampleLocationsInfo(m_pixelGrids[useSameSamplePattern() ? 0 : 1]), 2991 }; 2992 const bool useFragmentShadingRate (TEST_OPTION_FRAGMENT_SHADING_RATE_BIT & m_params.options); 2993 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex())); 2994 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 2995 Move<VkCommandBuffer> secondaryCmdBuffer; 2996 RenderTarget rt; 2997 std::vector<GraphicsPipelineWrapper> pipelines; 2998 Move<VkEvent> event; 2999 3000 // Prepare the render pass 3001 { 3002 rt.addAttachment( 3003 *m_colorImage, // VkImage image 3004 *m_colorImageView, // VkImageView imageView, 3005 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 3006 m_colorFormat, // VkFormat format, 3007 m_params.numSamples, // VkSampleCountFlagBits numSamples, 3008 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 3009 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 3010 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 3011 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 3012 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 3013 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 3014 clearColor0); // VkClearValue clearValue, 3015 3016 rt.addAttachment( 3017 *m_resolveImage, // VkImage image 3018 *m_resolveImageView, // VkImageView imageView, 3019 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 3020 m_colorFormat, // VkFormat format, 3021 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits numSamples, 3022 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp, 3023 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 3024 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp, 3025 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp, 3026 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 3027 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout finalLayout, 3028 VkClearValue()); // VkClearValue clearValue, 3029 3030 rt.addSubpassColorAttachmentWithResolve(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 3031 1u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 3032 3033 if (useDepth() || useStencil()) 3034 { 3035 rt.addAttachment( 3036 *m_depthStencilImage, // VkImage image 3037 *m_depthStencilImageView, // VkImageView imageView, 3038 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags, 3039 m_depthStencilFormat, // VkFormat format, 3040 m_params.numSamples, // VkSampleCountFlagBits numSamples, 3041 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp, 3042 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp, 3043 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp, 3044 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp, 3045 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout, 3046 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout, 3047 clearDepthStencil0, // VkClearValue clearValue, 3048 &sampleLocationsInfo[0]); // VkSampleLocationsInfoEXT* pInitialSampleLocations 3049 3050 rt.addSubpassDepthStencilAttachment(2u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, &sampleLocationsInfo[0]); 3051 } 3052 3053 rt.bake(vk, device, m_params.pipelineConstructionType, m_renderSize); 3054 } 3055 3056 // Pipelines 3057 pipelines.reserve(NUM_PASSES); 3058 if (useDynamicState()) 3059 { 3060 std::vector<VkDynamicState> dynamicState; 3061 dynamicState.push_back(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT); 3062 3063 for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 3064 { 3065 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 3066 preparePipelineWrapper(pipelines.back(), dynamicState, pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, 3067 /*subpass*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, makeEmptySampleLocationsInfo(), 3068 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate); 3069 } 3070 } 3071 else for (deUint32 passNdx = 0; passNdx < NUM_PASSES; ++passNdx) 3072 { 3073 pipelines.emplace_back(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 3074 preparePipelineWrapper(pipelines.back(), std::vector<VkDynamicState>(), pipelineLayout, rt.getRenderPass(), vertexModule, fragmentModule, 3075 /*subpass*/ 0u, viewport, scissor, m_params.numSamples, /*use sample locations*/ true, sampleLocationsInfo[passNdx], 3076 useDepth(), useStencil(), VERTEX_INPUT_VEC4_VEC4, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, stencilOpStateDrawOnce(), useFragmentShadingRate); 3077 } 3078 3079 // Record secondary command buffers 3080 3081 if (useSecondaryCmdBuffer()) 3082 { 3083 secondaryCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY); 3084 3085 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, rt.getRenderPassWrapper(), /*subpass*/ 0u, m_params.numSamples, m_params.pipelineConstructionType); 3086 recordFirstPassContents(*secondaryCmdBuffer, pipelines[0], sampleLocationsInfo[0]); 3087 recordSecondPassContents(*secondaryCmdBuffer, pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 3088 endCommandBuffer(vk, *secondaryCmdBuffer); 3089 } 3090 3091 // Record primary command buffer 3092 3093 beginCommandBuffer(vk, *cmdBuffer); 3094 3095 if (useSecondaryCmdBuffer()) 3096 { 3097 rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 3098 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get()); 3099 } 3100 else 3101 { 3102 rt.recordBeginRenderPass(vk, *cmdBuffer, renderArea, VK_SUBPASS_CONTENTS_INLINE); 3103 recordFirstPassContents(*cmdBuffer, pipelines[0], sampleLocationsInfo[0]); 3104 recordSecondPassContents(*cmdBuffer, pipelines[1], sampleLocationsInfo[1], clearColor1, clearDepthStencil0, scissor); 3105 } 3106 3107 rt.endRenderPass(vk, *cmdBuffer); 3108 3109 // Resolve image -> host buffer 3110 recordCopyImageToBuffer(vk, *cmdBuffer, m_renderSize, *m_resolveImage, *m_colorBuffer); 3111 3112 endCommandBuffer(vk, *cmdBuffer); 3113 3114 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer); 3115 invalidateAlloc(vk, device, *m_colorBufferAlloc); 3116 } 3117 3118 const TestParams m_params; 3119 const VkPhysicalDeviceSampleLocationsPropertiesEXT m_sampleLocationsProperties; 3120 const UVec2 m_renderSize; 3121 UVec2 m_gridSize; 3122 std::vector<MultisamplePixelGrid> m_pixelGrids; 3123 deUint32 m_numVertices; 3124 Move<VkBuffer> m_vertexBuffer; 3125 MovePtr<Allocation> m_vertexBufferAlloc; 3126 const VkFormat m_colorFormat; 3127 Move<VkImage> m_colorImage; 3128 Move<VkImageView> m_colorImageView; 3129 MovePtr<Allocation> m_colorImageAlloc; 3130 VkFormat m_depthStencilFormat; 3131 VkImageAspectFlags m_depthStencilAspect; 3132 Move<VkImage> m_depthStencilImage; 3133 Move<VkImageView> m_depthStencilImageView; 3134 MovePtr<Allocation> m_depthStencilImageAlloc; 3135 Move<VkImage> m_resolveImage; 3136 Move<VkImageView> m_resolveImageView; 3137 MovePtr<Allocation> m_resolveImageAlloc; 3138 Move<VkBuffer> m_colorBuffer; 3139 MovePtr<Allocation> m_colorBufferAlloc; 3140}; 3141 3142} // Draw 3143 3144void createTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate) 3145{ 3146 // Queries 3147 if (!useFragmentShadingRate && (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)) 3148 { 3149 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(rootGroup->getTestContext(), "query")); 3150 3151 addFunctionCase(group.get(), "sample_locations_properties", checkSupportSampleLocations, testQuerySampleLocationProperties); 3152 addFunctionCase(group.get(), "multisample_properties", checkSupportSampleLocations, testQueryMultisampleProperties); 3153 3154 rootGroup->addChild(group.release()); 3155 } 3156 3157 const VkSampleCountFlagBits sampleCountRange[] = 3158 { 3159 VK_SAMPLE_COUNT_2_BIT, 3160 VK_SAMPLE_COUNT_4_BIT, 3161 VK_SAMPLE_COUNT_8_BIT, 3162 VK_SAMPLE_COUNT_16_BIT, 3163 // There are no implementations that support 32 or 64 programmable samples currently 3164 }; 3165 3166 // Verify custom sample locations and interpolation 3167 { 3168 using namespace VerifySamples; 3169 3170 MovePtr<tcu::TestCaseGroup> groupLocation (new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_location")); 3171 MovePtr<tcu::TestCaseGroup> groupInterpolation (new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_interpolation")); 3172 3173 for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples) 3174 { 3175 addCases<VerifyLocationTest> (groupLocation.get(), *pLoopNumSamples, pipelineConstructionType, useFragmentShadingRate, addProgramsVerifyLocationGeometry); 3176 addCases<VerifyInterpolationTest>(groupInterpolation.get(), *pLoopNumSamples, pipelineConstructionType, useFragmentShadingRate, addProgramsVerifyInterpolation); 3177 } 3178 3179 rootGroup->addChild(groupLocation.release()); 3180 rootGroup->addChild(groupInterpolation.release()); 3181 } 3182 3183 // Draw with custom samples and various options 3184 { 3185 using namespace Draw; 3186 3187 const deUint32 globalOption = useFragmentShadingRate ? static_cast<deUint32>(TEST_OPTION_FRAGMENT_SHADING_RATE_BIT) : 0u; 3188 const deUint32 optionSets[] = 3189 { 3190 globalOption | TEST_OPTION_SAME_PATTERN_BIT, 3191 globalOption | 0u, 3192 globalOption | TEST_OPTION_DYNAMIC_STATE_BIT, 3193 globalOption | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT, 3194 globalOption | TEST_OPTION_DYNAMIC_STATE_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT, 3195 globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT, 3196 globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_DYNAMIC_STATE_BIT, 3197 globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT, 3198 globalOption | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_DYNAMIC_STATE_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT, 3199 globalOption | TEST_OPTION_WAIT_EVENTS_BIT, 3200 globalOption | TEST_OPTION_WAIT_EVENTS_BIT | TEST_OPTION_GENERAL_LAYOUT_BIT, 3201 globalOption | TEST_OPTION_WAIT_EVENTS_BIT | TEST_OPTION_GENERAL_LAYOUT_BIT | TEST_OPTION_SECONDARY_COMMAND_BUFFER_BIT, 3202 }; 3203 3204 const struct 3205 { 3206 TestDrawIn drawIn; 3207 TestClears clears; 3208 } drawClearSets[] = 3209 { 3210 { TEST_DRAW_IN_RENDER_PASSES, TEST_CLEARS_NO_CLEAR }, 3211 { TEST_DRAW_IN_RENDER_PASSES, TEST_CLEARS_LOAD_OP_CLEAR }, 3212 { TEST_DRAW_IN_RENDER_PASSES, TEST_CLEARS_CMD_CLEAR_ATTACHMENTS }, 3213 { TEST_DRAW_IN_RENDER_PASSES, TEST_CLEARS_CMD_CLEAR_IMAGE }, 3214 { TEST_DRAW_IN_SUBPASSES, TEST_CLEARS_NO_CLEAR }, 3215 { TEST_DRAW_IN_SUBPASSES, TEST_CLEARS_CMD_CLEAR_ATTACHMENTS }, 3216 { TEST_DRAW_IN_SAME_SUBPASS, TEST_CLEARS_NO_CLEAR }, 3217 { TEST_DRAW_IN_SAME_SUBPASS, TEST_CLEARS_CMD_CLEAR_ATTACHMENTS }, 3218 }; 3219 3220 const TestImageAspect aspectRange[] = 3221 { 3222 TEST_IMAGE_ASPECT_COLOR, 3223 TEST_IMAGE_ASPECT_DEPTH, 3224 TEST_IMAGE_ASPECT_STENCIL, 3225 }; 3226 3227 MovePtr<tcu::TestCaseGroup> drawGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "draw")); 3228 for (const TestImageAspect* pLoopImageAspect = aspectRange; pLoopImageAspect != DE_ARRAY_END(aspectRange); ++pLoopImageAspect) 3229 { 3230 MovePtr<tcu::TestCaseGroup> aspectGroup (new tcu::TestCaseGroup(drawGroup->getTestContext(), getString(*pLoopImageAspect))); 3231 for (const VkSampleCountFlagBits* pLoopNumSamples = sampleCountRange; pLoopNumSamples < DE_ARRAY_END(sampleCountRange); ++pLoopNumSamples) 3232 { 3233 MovePtr<tcu::TestCaseGroup> samplesGroup (new tcu::TestCaseGroup(aspectGroup->getTestContext(), getString(*pLoopNumSamples).c_str())); 3234 3235 for (deUint32 loopDrawSetNdx = 0u; loopDrawSetNdx < DE_LENGTH_OF_ARRAY(drawClearSets); ++loopDrawSetNdx) 3236 for (const deUint32* pLoopOptions = optionSets; pLoopOptions != DE_ARRAY_END(optionSets); ++pLoopOptions) 3237 { 3238 const TestParams params 3239 { 3240 pipelineConstructionType, // PipelineConstructionType pipelineConstructionType; 3241 *pLoopNumSamples, // VkSampleCountFlagBits numSamples; 3242 *pLoopOptions, // TestOptionFlags options; 3243 drawClearSets[loopDrawSetNdx].drawIn, // TestDrawIn drawIn; 3244 drawClearSets[loopDrawSetNdx].clears, // TestClears clears; 3245 *pLoopImageAspect, // TestImageAspect imageAspect; 3246 }; 3247 3248 // Filter out incompatible parameter combinations 3249 if (params.imageAspect != TEST_IMAGE_ASPECT_COLOR) 3250 { 3251 // If the sample pattern is changed, the D/S image must be cleared or the result is undefined 3252 if (((params.options & TEST_OPTION_SAME_PATTERN_BIT) == 0u) && (params.clears == TEST_CLEARS_NO_CLEAR)) 3253 continue; 3254 } 3255 3256 // We are using events to change image layout and this is only allowed outside a render pass 3257 if (((params.options & TEST_OPTION_WAIT_EVENTS_BIT) != 0u) && (params.drawIn != TEST_DRAW_IN_RENDER_PASSES)) 3258 continue; 3259 3260 // Can't change image layout inside a subpass 3261 if (((params.options & TEST_OPTION_GENERAL_LAYOUT_BIT) != 0u) && (params.drawIn == TEST_DRAW_IN_SAME_SUBPASS)) 3262 continue; 3263 3264 std::ostringstream caseName; 3265 caseName << getString(params.drawIn) << "_" 3266 << getString(params.clears) << (params.options != 0 ? "_" : "") 3267 << getTestOptionFlagsString(params.options); 3268 3269 addInstanceTestCaseWithPrograms<DrawTest>(samplesGroup.get(), caseName.str().c_str(), checkSupportDrawTests, initPrograms, params); 3270 } 3271 aspectGroup->addChild(samplesGroup.release()); 3272 } 3273 drawGroup->addChild(aspectGroup.release()); 3274 } 3275 rootGroup->addChild(drawGroup.release()); 3276 } 3277} 3278 3279} // anonymous ns 3280 3281tcu::TestCaseGroup* createMultisampleSampleLocationsExtTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate) 3282{ 3283 return createTestGroup(testCtx, "sample_locations_ext", createTestsInGroup, pipelineConstructionType, useFragmentShadingRate); 3284} 3285 3286} // pipeline 3287} // vkt 3288