1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2020 The Khronos Group Inc. 6 * Copyright (c) 2020 Valve Corporation 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Vulkan Concurrent Query Tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktQueryPoolConcurrentTests.hpp" 26 27#include "vktTestCase.hpp" 28 29#include "vktDrawImageObjectUtil.hpp" 30#include "vktDrawBufferObjectUtil.hpp" 31#include "vktDrawCreateInfoUtil.hpp" 32#include "vkBuilderUtil.hpp" 33#include "vkRef.hpp" 34#include "vkRefUtil.hpp" 35#include "vkTypeUtil.hpp" 36#include "vkCmdUtil.hpp" 37#include "vkQueryUtil.hpp" 38 39#include "tcuTestLog.hpp" 40#include "tcuImageCompare.hpp" 41 42#include <memory> 43 44namespace vkt 45{ 46 47namespace QueryPool 48{ 49 50using namespace Draw; 51 52namespace 53{ 54 55enum QueryType 56{ 57 QUERY_TYPE_OCCLUSION = vk::VK_QUERY_TYPE_OCCLUSION, 58 QUERY_TYPE_PIPELINE_STATISTICS = vk::VK_QUERY_TYPE_PIPELINE_STATISTICS, 59 QUERY_TYPE_TIMESTAMP = vk::VK_QUERY_TYPE_TIMESTAMP, 60 NUM_QUERY_POOLS = 3 61}; 62 63struct StateObjects 64{ 65 StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive); 66 void setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices); 67 68 enum 69 { 70 WIDTH = 128, 71 HEIGHT = 128 72 }; 73 74 vkt::Context &m_context; 75 76 vk::Move<vk::VkPipeline> m_pipeline; 77 vk::Move<vk::VkPipelineLayout> m_pipelineLayout; 78 79 de::SharedPtr<Image> m_colorAttachmentImage, m_DepthImage; 80 vk::Move<vk::VkImageView> m_attachmentView; 81 vk::Move<vk::VkImageView> m_depthiew; 82 83 vk::Move<vk::VkRenderPass> m_renderPass; 84 vk::Move<vk::VkFramebuffer> m_framebuffer; 85 86 de::SharedPtr<Buffer> m_vertexBuffer; 87 88 vk::VkFormat m_colorAttachmentFormat; 89}; 90 91StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive) 92 : m_context(context) 93 , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM) 94 95{ 96 vk::VkFormat depthFormat = vk::VK_FORMAT_D16_UNORM; 97 const vk::VkDevice device = m_context.getDevice(); 98 99 //attachment images and views 100 { 101 vk::VkExtent3D imageExtent = 102 { 103 WIDTH, // width; 104 HEIGHT, // height; 105 1 // depth; 106 }; 107 108 const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL, 109 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT); 110 111 m_colorAttachmentImage = Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex()); 112 113 const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat); 114 m_attachmentView = vk::createImageView(vk, device, &attachmentViewInfo); 115 116 ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL, 117 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); 118 119 m_DepthImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex()); 120 121 // Construct a depth view from depth image 122 const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat); 123 m_depthiew = vk::createImageView(vk, device, &depthViewInfo); 124 } 125 126 { 127 // Renderpass and Framebuffer 128 129 RenderPassCreateInfo renderPassCreateInfo; 130 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat, // format 131 vk::VK_SAMPLE_COUNT_1_BIT, // samples 132 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp 133 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp 134 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp 135 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp 136 vk::VK_IMAGE_LAYOUT_GENERAL, // initialLauout 137 vk::VK_IMAGE_LAYOUT_GENERAL)); // finalLayout 138 139 renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat, // format 140 vk::VK_SAMPLE_COUNT_1_BIT, // samples 141 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp 142 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp 143 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp 144 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp 145 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLauout 146 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout 147 148 const vk::VkAttachmentReference colorAttachmentReference = 149 { 150 0, // attachment 151 vk::VK_IMAGE_LAYOUT_GENERAL // layout 152 }; 153 154 const vk::VkAttachmentReference depthAttachmentReference = 155 { 156 1, // attachment 157 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // layout 158 }; 159 160 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint 161 0, // flags 162 0, // inputCount 163 DE_NULL, // pInputAttachments 164 1, // colorCount 165 &colorAttachmentReference, // pColorAttachments 166 DE_NULL, // pResolveAttachments 167 depthAttachmentReference, // depthStencilAttachment 168 0, // preserveCount 169 DE_NULL)); // preserveAttachments 170 171 m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo); 172 173 std::vector<vk::VkImageView> attachments(2); 174 attachments[0] = *m_attachmentView; 175 attachments[1] = *m_depthiew; 176 177 FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1); 178 m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo); 179 } 180 181 { 182 // Pipeline 183 184 vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); 185 vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); 186 187 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState; 188 189 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo; 190 m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo); 191 192 const vk::VkVertexInputBindingDescription vf_binding_desc = 193 { 194 0, // binding; 195 4 * (deUint32)sizeof(float), // stride; 196 vk::VK_VERTEX_INPUT_RATE_VERTEX // inputRate 197 }; 198 199 const vk::VkVertexInputAttributeDescription vf_attribute_desc = 200 { 201 0, // location; 202 0, // binding; 203 vk::VK_FORMAT_R32G32B32A32_SFLOAT, // format; 204 0 // offset; 205 }; 206 207 const vk::VkPipelineVertexInputStateCreateInfo vf_info = 208 { // sType; 209 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // pNext; 210 NULL, // flags; 211 0u, // vertexBindingDescriptionCount; 212 1, // pVertexBindingDescriptions; 213 &vf_binding_desc, // vertexAttributeDescriptionCount; 214 1, // pVertexAttributeDescriptions; 215 &vf_attribute_desc 216 }; 217 218 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0); 219 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT)); 220 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT)); 221 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive)); 222 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState)); 223 const vk::VkViewport viewport = vk::makeViewport(WIDTH, HEIGHT); 224 const vk::VkRect2D scissor = vk::makeRect2D(WIDTH, HEIGHT); 225 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor))); 226 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL)); 227 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState()); 228 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState()); 229 pipelineCreateInfo.addState(vf_info); 230 m_pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo); 231 } 232 233 { 234 // Vertex buffer 235 const size_t kBufferSize = numVertices * sizeof(tcu::Vec4); 236 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible); 237 } 238} 239 240void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices) 241{ 242 const vk::VkDevice device = m_context.getDevice(); 243 244 tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_vertexBuffer->getBoundMemory().getHostPtr()); 245 std::copy(vertices.begin(), vertices.end(), ptr); 246 247 vk::flushAlloc(vk, device, m_vertexBuffer->getBoundMemory()); 248} 249 250class PrimaryCommandBufferConcurrentTestInstance : public vkt::TestInstance 251{ 252public: 253 PrimaryCommandBufferConcurrentTestInstance (vkt::Context &context); 254 ~PrimaryCommandBufferConcurrentTestInstance (void); 255private: 256 tcu::TestStatus iterate (void); 257 258 enum 259 { 260 NUM_QUERIES_IN_POOL = 2, 261 QUERY_INDEX_CAPTURE_EMPTY = 0, 262 QUERY_INDEX_CAPTURE_DRAWCALL = 1, 263 NUM_VERTICES_IN_DRAWCALL = 3 264 }; 265 266 std::unique_ptr<StateObjects> m_stateObjects; 267 vk::Move<vk::VkQueryPool> m_queryPools[NUM_QUERY_POOLS]; 268 deBool m_supportedQueryType[NUM_QUERY_POOLS]; 269}; 270 271PrimaryCommandBufferConcurrentTestInstance::PrimaryCommandBufferConcurrentTestInstance (vkt::Context &context) 272 : TestInstance (context) 273{ 274 // Check support for multiple query types 275 { 276 for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++) 277 m_supportedQueryType[poolNdx] = DE_FALSE; 278 279 deUint32 numSupportedQueryTypes = 0; 280 m_supportedQueryType[QUERY_TYPE_OCCLUSION] = DE_TRUE; 281 numSupportedQueryTypes++; 282 283 if (context.getDeviceFeatures().pipelineStatisticsQuery) 284 { 285 m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = DE_TRUE; 286 numSupportedQueryTypes++; 287 } 288 289 // Check support for timestamp queries 290 { 291 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 292 const std::vector<vk::VkQueueFamilyProperties> queueProperties = vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice()); 293 294 DE_ASSERT(queueFamilyIndex < (deUint32)queueProperties.size()); 295 296 if (queueProperties[queueFamilyIndex].timestampValidBits) 297 { 298 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = DE_TRUE; 299 numSupportedQueryTypes++; 300 } 301 } 302 if (numSupportedQueryTypes < 2) 303 throw tcu::NotSupportedError("Device does not support multiple query types"); 304 } 305 306 m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); 307 308 const vk::VkDevice device = m_context.getDevice(); 309 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 310 311 for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++) 312 { 313 if (!m_supportedQueryType[poolNdx]) 314 continue; 315 316 vk::VkQueryPoolCreateInfo queryPoolCreateInfo = 317 { 318 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 319 DE_NULL, 320 0u, 321 static_cast<vk::VkQueryType>(poolNdx), 322 NUM_QUERIES_IN_POOL, 323 0u, 324 }; 325 if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS) 326 queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT; 327 328 m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL); 329 } 330 331 std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL); 332 vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0); 333 vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0); 334 vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0); 335 m_stateObjects->setVertices(vk, vertices); 336} 337 338PrimaryCommandBufferConcurrentTestInstance::~PrimaryCommandBufferConcurrentTestInstance (void) 339{ 340} 341 342tcu::TestStatus PrimaryCommandBufferConcurrentTestInstance::iterate (void) 343{ 344 tcu::TestLog &log = m_context.getTestContext().getLog(); 345 const vk::VkDevice device = m_context.getDevice(); 346 const vk::VkQueue queue = m_context.getUniversalQueue(); 347 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 348 349 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex()); 350 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo); 351 352 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 353 354 beginCommandBuffer(vk, *cmdBuffer); 355 356 initialTransitionColor2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 357 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); 358 initialTransitionDepth2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 359 vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); 360 361 std::vector<vk::VkClearValue> renderPassClearValues(2); 362 deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue)); 363 364 for (deUint32 poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++) 365 { 366 if (m_supportedQueryType[poolNdx]) 367 vk.cmdResetQueryPool(*cmdBuffer, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL); 368 } 369 370 beginRenderPass(vk, *cmdBuffer, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT), (deUint32)renderPassClearValues.size(), &renderPassClearValues[0]); 371 372 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline); 373 374 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object(); 375 const vk::VkDeviceSize vertexBufferOffset = 0; 376 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset); 377 378 // Begin all queries 379 for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 380 { 381 if (m_supportedQueryType[poolNdx]) 382 vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u); 383 } 384 385 // End first capture (should not have any result). Start the second one. 386 for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 387 { 388 if (m_supportedQueryType[poolNdx]) 389 { 390 vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY); 391 vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_DRAWCALL, 0u); 392 } 393 } 394 395 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0); 396 397 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP]) 398 vk.cmdWriteTimestamp(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL); 399 400 for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 401 { 402 if (m_supportedQueryType[poolNdx]) 403 vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_DRAWCALL); 404 } 405 406 endRenderPass(vk, *cmdBuffer); 407 408 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, 409 vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 410 vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT); 411 412 endCommandBuffer(vk, *cmdBuffer); 413 414 submitCommandsAndWait(vk, device, queue, cmdBuffer.get()); 415 416 deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 }; 417 size_t queryResultsSize = sizeof(queryResults); 418 bool passed = true; 419 420 // Occlusion and pipeline statistics queries verification 421 for (deUint32 poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 422 { 423 if (m_supportedQueryType[poolNdx] == DE_FALSE) 424 continue; 425 vk::VkResult queryResult = vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT); 426 427 if (queryResult == vk::VK_NOT_READY) 428 { 429 TCU_FAIL("Query result not available, but vkWaitIdle() was called."); 430 } 431 432 VK_CHECK(queryResult); 433 std::string name = (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults"; 434 std::string desc = (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results"; 435 log << tcu::TestLog::Section(name, desc); 436 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx) 437 { 438 log << tcu::TestLog::Message << "query[slot == " << ndx 439 << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage; 440 } 441 442 443 for (deUint32 queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx) 444 { 445 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u) 446 { 447 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 448 "wrong value of query for index " 449 << queryNdx << ", expected any zero value, got " 450 << queryResults[0] << "." << tcu::TestLog::EndMessage; 451 passed = false; 452 } 453 454 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0) 455 { 456 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 457 "wrong value of query for index " 458 << queryNdx << ", expected any non-zero value, got " 459 << queryResults[0] << "." << tcu::TestLog::EndMessage; 460 passed = false; 461 } 462 } 463 log << tcu::TestLog::EndSection; 464 } 465 466 // Timestamp query verification 467 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP]) 468 { 469 std::pair<deUint64, deUint64> queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL]; 470 size_t queryResultsWithAvailabilityBitSize = sizeof(queryResultsWithAvailabilityBit); 471 vk::VkResult queryResult = vk.getQueryPoolResults(device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize, &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]), vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); 472 473 if (queryResult != vk::VK_NOT_READY) 474 { 475 TCU_FAIL("We don't have available one query, it should return VK_NOT_READY"); 476 } 477 478 log << tcu::TestLog::Section("TimestampQueryResults", 479 "Timestamp query results"); 480 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx) 481 { 482 log << tcu::TestLog::Message << "query[slot == " << ndx 483 << "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage; 484 } 485 486 487 for (deUint32 queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx) 488 { 489 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u || queryResultsWithAvailabilityBit[queryNdx].second != 0u)) 490 { 491 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 492 "either wrong value of query for index " 493 << queryNdx << " (expected any zero value, got " 494 << queryResultsWithAvailabilityBit[queryNdx].first << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")" 495 << tcu::TestLog::EndMessage; 496 passed = false; 497 } 498 499 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u || queryResultsWithAvailabilityBit[queryNdx].second == 0u)) 500 { 501 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 502 "either wrong value of query for index " 503 << queryNdx << " (expected any non-zero value, got " 504 << queryResults[0] << ") or result is unavailable." << tcu::TestLog::EndMessage; 505 passed = false; 506 } 507 } 508 log << tcu::TestLog::EndSection; 509 } 510 511 if (passed) 512 { 513 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed"); 514 } 515 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed"); 516} 517 518class SecondaryCommandBufferConcurrentTestInstance : public vkt::TestInstance 519{ 520public: 521 SecondaryCommandBufferConcurrentTestInstance (vkt::Context &context); 522 ~SecondaryCommandBufferConcurrentTestInstance (void); 523private: 524 tcu::TestStatus iterate (void); 525 526 enum 527 { 528 NUM_QUERIES_IN_POOL = 2, 529 QUERY_INDEX_CAPTURE_EMPTY = 0, 530 QUERY_INDEX_CAPTURE_DRAWCALL = 1, 531 NUM_VERTICES_IN_DRAWCALL = 3 532 }; 533 534 std::unique_ptr<StateObjects> m_stateObjects; 535 vk::Move<vk::VkQueryPool> m_queryPools[NUM_QUERY_POOLS]; 536 deBool m_supportedQueryType[NUM_QUERY_POOLS]; 537 538}; 539 540SecondaryCommandBufferConcurrentTestInstance::SecondaryCommandBufferConcurrentTestInstance (vkt::Context &context) 541 : TestInstance (context) 542{ 543 // Check support for multiple query types 544 { 545 for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++) 546 m_supportedQueryType[poolNdx] = DE_FALSE; 547 548 deUint32 numSupportedQueryTypes = 0; 549 m_supportedQueryType[QUERY_TYPE_OCCLUSION] = DE_TRUE; 550 numSupportedQueryTypes++; 551 552 if (context.getDeviceFeatures().pipelineStatisticsQuery) 553 { 554 m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = DE_TRUE; 555 numSupportedQueryTypes++; 556 } 557 558 // Check support for timestamp queries 559 { 560 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 561 const std::vector<vk::VkQueueFamilyProperties> queueProperties = vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice()); 562 563 DE_ASSERT(queueFamilyIndex < (deUint32)queueProperties.size()); 564 565 if (queueProperties[queueFamilyIndex].timestampValidBits) 566 { 567 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = DE_TRUE; 568 numSupportedQueryTypes++; 569 } 570 } 571 if (numSupportedQueryTypes < 2) 572 throw tcu::NotSupportedError("Device does not support multiple query types"); 573 } 574 575 m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)); 576 577 const vk::VkDevice device = m_context.getDevice(); 578 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 579 580 for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++) 581 { 582 if (!m_supportedQueryType[poolNdx]) 583 continue; 584 585 vk::VkQueryPoolCreateInfo queryPoolCreateInfo = 586 { 587 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, 588 DE_NULL, 589 0u, 590 static_cast<vk::VkQueryType>(poolNdx), 591 NUM_QUERIES_IN_POOL, 592 0u, 593 }; 594 if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS) 595 queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT; 596 597 m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL); 598 } 599 600 std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL); 601 vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0); 602 vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0); 603 vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0); 604 m_stateObjects->setVertices(vk, vertices); 605} 606 607SecondaryCommandBufferConcurrentTestInstance::~SecondaryCommandBufferConcurrentTestInstance (void) 608{ 609} 610 611void beginSecondaryCommandBuffer (const vk::DeviceInterface& vk, 612 const vk::VkCommandBuffer secondaryCmdBuffer, 613 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo) 614{ 615 const vk::VkCommandBufferUsageFlags flags = bufferInheritanceInfo.renderPass != DE_NULL 616 ? (vk::VkCommandBufferUsageFlags)vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT 617 : (vk::VkCommandBufferUsageFlags)0u; 618 const vk::VkCommandBufferBeginInfo beginInfo = 619 { 620 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType 621 DE_NULL, // pNext 622 flags, // flags 623 &bufferInheritanceInfo, // pInheritanceInfo 624 }; 625 VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffer, &beginInfo)); 626} 627 628tcu::TestStatus SecondaryCommandBufferConcurrentTestInstance::iterate (void) 629{ 630 tcu::TestLog &log = m_context.getTestContext().getLog(); 631 const vk::VkDevice device = m_context.getDevice(); 632 const vk::VkQueue queue = m_context.getUniversalQueue(); 633 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 634 const deBool inheritedQueries = m_context.getDeviceFeatures().inheritedQueries; 635 636 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex()); 637 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo); 638 639 vk::Unique<vk::VkCommandBuffer> cmdBufferPrimary (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 640 vk::Unique<vk::VkCommandBuffer> cmdBufferSecondary (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY)); 641 642 // Secondary command buffer recording. 643 { 644 // Begin secondary command buffer 645 const vk::VkCommandBufferInheritanceInfo secCmdBufInheritInfo = 646 { 647 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 648 DE_NULL, 649 *m_stateObjects->m_renderPass, // renderPass 650 0u, // subpass 651 *m_stateObjects->m_framebuffer, // framebuffer 652 inheritedQueries ? VK_TRUE : VK_FALSE, // occlusionQueryEnable 653 (vk::VkQueryControlFlags)0u, // queryFlags 654 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics 655 }; 656 beginSecondaryCommandBuffer(vk, *cmdBufferSecondary, secCmdBufInheritInfo); 657 658 vk.cmdBindPipeline(*cmdBufferSecondary, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline); 659 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object(); 660 const vk::VkDeviceSize vertexBufferOffset = 0; 661 vk.cmdBindVertexBuffers(*cmdBufferSecondary, 0, 1, &vertexBuffer, &vertexBufferOffset); 662 663 if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION]) 664 vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL, 0u); 665 666 // Run pipeline statistics queries capture in the second command buffer 667 if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS]) 668 vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS], QUERY_INDEX_CAPTURE_DRAWCALL, 0u); 669 670 // Timestamp query happening in the secondary command buffer 671 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP]) 672 vk.cmdWriteTimestamp(*cmdBufferSecondary, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL); 673 674 vk.cmdDraw(*cmdBufferSecondary, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0); 675 676 if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS]) 677 vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS], QUERY_INDEX_CAPTURE_DRAWCALL); 678 679 if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION]) 680 vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL); 681 682 endCommandBuffer(vk, *cmdBufferSecondary); 683 } 684 685 // Primary command buffer recording 686 { 687 beginCommandBuffer(vk, *cmdBufferPrimary); 688 689 initialTransitionColor2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, 690 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); 691 initialTransitionDepth2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 692 vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT); 693 694 std::vector<vk::VkClearValue> renderPassClearValues(2); 695 deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue)); 696 697 for (deUint32 poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++) 698 { 699 if (m_supportedQueryType[poolNdx]) 700 vk.cmdResetQueryPool(*cmdBufferPrimary, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL); 701 } 702 703 for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 704 { 705 if (m_supportedQueryType[poolNdx]) 706 vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u); 707 } 708 709 for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 710 { 711 if (m_supportedQueryType[poolNdx]) 712 vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY); 713 } 714 715 // Run oclussion queries capture in the primary command buffer, inherit the counters for the secondary command buffer 716 if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION]) 717 vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL, 0u); 718 719 beginRenderPass(vk, *cmdBufferPrimary, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT), (deUint32)renderPassClearValues.size(), &renderPassClearValues[0], vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 720 721 vk.cmdExecuteCommands(*cmdBufferPrimary, 1u, &cmdBufferSecondary.get()); 722 723 endRenderPass(vk, *cmdBufferPrimary); 724 725 if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION]) 726 vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL); 727 728 transition2DImage(vk, *cmdBufferPrimary, 729 m_stateObjects->m_colorAttachmentImage->object(), 730 vk::VK_IMAGE_ASPECT_COLOR_BIT, 731 vk::VK_IMAGE_LAYOUT_GENERAL, 732 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 733 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 734 vk::VK_ACCESS_TRANSFER_READ_BIT, 735 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 736 vk::VK_PIPELINE_STAGE_TRANSFER_BIT); 737 738 endCommandBuffer(vk, *cmdBufferPrimary); 739 } 740 741 submitCommandsAndWait(vk, device, queue, cmdBufferPrimary.get()); 742 743 deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 }; 744 size_t queryResultsSize = sizeof(queryResults); 745 bool passed = true; 746 747 // Occlusion and pipeline statistics queries verification 748 for (deUint32 poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++) 749 { 750 if (!m_supportedQueryType[poolNdx]) 751 continue; 752 vk::VkResult queryResult = vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT); 753 754 if (queryResult == vk::VK_NOT_READY) 755 { 756 TCU_FAIL("Query result not available, but vkWaitIdle() was called."); 757 } 758 759 VK_CHECK(queryResult); 760 std::string name = (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults"; 761 std::string desc = (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results"; 762 log << tcu::TestLog::Section(name, desc); 763 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx) 764 { 765 log << tcu::TestLog::Message << "query[slot == " << ndx 766 << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage; 767 } 768 769 for (deUint32 queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx) 770 { 771 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u) 772 { 773 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 774 "wrong value of query for index " 775 << queryNdx << ", expected any zero value, got " 776 << queryResults[0] << "." << tcu::TestLog::EndMessage; 777 passed = false; 778 } 779 780 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0) 781 { 782 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 783 "wrong value of query for index " 784 << queryNdx << ", expected any non-zero value, got " 785 << queryResults[0] << "." << tcu::TestLog::EndMessage; 786 passed = false; 787 } 788 } 789 log << tcu::TestLog::EndSection; 790 } 791 792 // Timestamp query verification 793 if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP]) 794 { 795 std::pair<deUint64, deUint64> queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL]; 796 size_t queryResultsWithAvailabilityBitSize = sizeof(queryResultsWithAvailabilityBit); 797 vk::VkResult queryResult = vk.getQueryPoolResults(device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize, &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]), vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); 798 799 if (queryResult != vk::VK_NOT_READY) 800 { 801 TCU_FAIL("We don't have available one query, it should return VK_NOT_READY"); 802 } 803 804 log << tcu::TestLog::Section("TimestampQueryResults", 805 "Timestamp query results"); 806 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx) 807 { 808 log << tcu::TestLog::Message << "query[slot == " << ndx 809 << "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage; 810 } 811 812 813 for (deUint32 queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx) 814 { 815 if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u || queryResultsWithAvailabilityBit[queryNdx].second != 0u)) 816 { 817 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 818 "either wrong value of query for index " 819 << queryNdx << " (expected any zero value, got " 820 << queryResultsWithAvailabilityBit[queryNdx].first << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")" 821 << tcu::TestLog::EndMessage; 822 passed = false; 823 } 824 825 if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u || queryResultsWithAvailabilityBit[queryNdx].second == 0u)) 826 { 827 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned " 828 "either wrong value of query for index " 829 << queryNdx << " (expected any non-zero value, got " 830 << queryResults[0] << ") or result is unavailable." << tcu::TestLog::EndMessage; 831 passed = false; 832 } 833 } 834 log << tcu::TestLog::EndSection; 835 } 836 837 if (passed) 838 { 839 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed"); 840 } 841 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed"); 842} 843 844template<class Instance> 845class QueryPoolConcurrentTest : public vkt::TestCase 846{ 847public: 848 QueryPoolConcurrentTest (tcu::TestContext &context, const char *name) 849 : TestCase (context, name) 850 { 851 } 852private: 853 vkt::TestInstance* createInstance (vkt::Context& context) const 854 { 855 return new Instance(context); 856 } 857 858 void initPrograms(vk::SourceCollections& programCollection) const 859 { 860 const std::string fragSrc = std::string( 861 "#version 400\n" 862 "layout(location = 0) out vec4 out_FragColor;\n" 863 "void main()\n" 864 "{\n" 865 " out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n" 866 " if ((int(gl_FragCoord.x) % 2) == (int(gl_FragCoord.y) % 2))\n" 867 " discard;\n" 868 "}"); 869 870 programCollection.glslSources.add("frag") << glu::FragmentSource(fragSrc.c_str()); 871 872 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n" 873 "layout(location = 0) in vec4 in_Position;\n" 874 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n" 875 "void main() {\n" 876 " gl_Position = in_Position;\n" 877 " gl_PointSize = 1.0;\n" 878 "}\n"); 879 } 880}; 881 882} //anonymous 883 884QueryPoolConcurrentTests::QueryPoolConcurrentTests (tcu::TestContext &testCtx) 885 : TestCaseGroup(testCtx, "concurrent_queries") 886{ 887 /* Left blank on purpose */ 888} 889 890QueryPoolConcurrentTests::~QueryPoolConcurrentTests (void) 891{ 892 /* Left blank on purpose */ 893} 894 895void QueryPoolConcurrentTests::init (void) 896{ 897 addChild(new QueryPoolConcurrentTest<PrimaryCommandBufferConcurrentTestInstance>(m_testCtx, "primary_command_buffer")); 898 addChild(new QueryPoolConcurrentTest<SecondaryCommandBufferConcurrentTestInstance>(m_testCtx, "secondary_command_buffer")); 899} 900 901} //QueryPool 902} //vkt 903