query_pool test: always wait for vkCmdCopyQueryResults to complete
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / query_pool / vktQueryPoolOcclusionTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and/or associated documentation files (the
10  * "Materials"), to deal in the Materials without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Materials, and to
13  * permit persons to whom the Materials are furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice(s) and this permission notice shall be included
17  * in all copies or substantial portions of the Materials.
18  *
19  * The Materials are Confidential Information as defined by the
20  * Khronos Membership Agreement until designated non-confidential by Khronos,
21  * at which point this condition clause shall be removed.
22  *
23  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30  *
31  *//*!
32  * \file
33  * \brief Vulkan Occlusion Query Tests
34  *//*--------------------------------------------------------------------*/
35
36 #include "vktQueryPoolOcclusionTests.hpp"
37
38 #include "vktTestCase.hpp"
39
40 #include "vktQueryPoolImageObjectUtil.hpp"
41 #include "vktQueryPoolBufferObjectUtil.hpp"
42 #include "vktQueryPoolCreateInfoUtil.hpp"
43 #include "vkBuilderUtil.hpp"
44 #include "vkRefUtil.hpp"
45 #include "vkPrograms.hpp"
46
47 #include "tcuTestLog.hpp"
48 #include "tcuResource.hpp"
49 #include "tcuImageCompare.hpp"
50 #include "tcuCommandLine.hpp"
51
52 using namespace vkt::QueryPool;
53
54 namespace
55 {
56
57 struct StateObjects {
58                         StateObjects    (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive);
59         void    setVertices             (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices);
60
61         enum
62         {
63                 WIDTH   = 128,
64                 HEIGHT  = 128
65         };
66
67         vkt::Context &m_context;
68
69         vk::Move<vk::VkPipeline>                m_Pipeline;
70         vk::Move<vk::VkPipelineLayout>  m_PipelineLayout;
71
72         de::SharedPtr<Image>                    m_ColorAttachmentImage, m_DepthImage;
73         vk::Move<vk::VkImageView>               m_AttachmentView;
74         vk::Move<vk::VkImageView>               m_DepthView;
75
76         vk::Move<vk::VkRenderPass>              m_RenderPass;
77         vk::Move<vk::VkFramebuffer>             m_Framebuffer;
78
79         de::SharedPtr<Buffer>                   m_VertexBuffer;
80
81         vk::VkFormat                                    m_ColorAttachmentFormat;
82 };
83
84 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
85         : m_context(context)
86         , m_ColorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
87
88 {
89         vk::VkFormat            depthFormat = vk::VK_FORMAT_D16_UNORM;
90         const vk::VkDevice      device          = m_context.getDevice();
91
92         //attachment images and views
93         {
94                 vk::VkExtent3D imageExtent =
95                 {
96                         WIDTH,  // width;
97                         HEIGHT, // height;
98                         1               // depth;
99                 };
100
101                 const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_ColorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
102                                                                                                    vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
103
104                 m_ColorAttachmentImage  = Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator());
105
106                 const ImageViewCreateInfo attachmentViewInfo(m_ColorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_ColorAttachmentFormat);
107                 m_AttachmentView                = vk::createImageView(vk, device, &attachmentViewInfo);
108
109                 ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
110                         vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
111
112                 m_DepthImage                    = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator());
113
114                 // Construct a depth  view from depth image
115                 const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
116                 m_DepthView                             = vk::createImageView(vk, device, &depthViewInfo);
117         }
118
119         {
120                 // Renderpass and Framebuffer
121
122                 RenderPassCreateInfo renderPassCreateInfo;
123                 renderPassCreateInfo.addAttachment(AttachmentDescription(m_ColorAttachmentFormat,                                                                       // format
124                                                                                                                                         vk::VK_SAMPLE_COUNT_1_BIT,                                                              // samples
125                                                                                                                                         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                                // loadOp
126                                                                                                                                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // storeOp
127                                                                                                                                         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                    // stencilLoadOp
128                                                                                                                                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // stencilLoadOp
129                                                                                                                                         vk::VK_IMAGE_LAYOUT_GENERAL,                                                    // initialLauout
130                                                                                                                                         vk::VK_IMAGE_LAYOUT_GENERAL));                                                  // finalLayout
131
132                 renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat,                                                                                           // format
133                                                                                                                                  vk::VK_SAMPLE_COUNT_1_BIT,                                                                     // samples
134                                                                                                                                  vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                                       // loadOp
135                                                                                                                                  vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                          // storeOp
136                                                                                                                                  vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                           // stencilLoadOp
137                                                                                                                                  vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                          // stencilLoadOp
138                                                                                                                                  vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,          // initialLauout
139                                                                                                                                  vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));        // finalLayout
140                         
141                 const vk::VkAttachmentReference colorAttachmentReference =
142                 {
143                         0,                                                                                                                      // attachment
144                         vk::VK_IMAGE_LAYOUT_GENERAL                                                                     // layout
145                 };
146
147                 const vk::VkAttachmentReference depthAttachmentReference =
148                 {
149                         1,                                                                                                                      // attachment
150                         vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL            // layout
151                 };
152
153                 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                                 // pipelineBindPoint
154                                                                                                                    0,                                                                                                   // flags
155                                                                                                                    0,                                                                                                   // inputCount
156                                                                                                                    DE_NULL,                                                                                             // pInputAttachments
157                                                                                                                    1,                                                                                                   // colorCount
158                                                                                                                    &colorAttachmentReference,                                                   // pColorAttachments
159                                                                                                                    DE_NULL,                                                                                             // pResolveAttachments
160                                                                                                                    depthAttachmentReference,                                                    // depthStencilAttachment
161                                                                                                                    0,                                                                                                   // preserveCount
162                                                                                                                    DE_NULL));                                                                                   // preserveAttachments
163
164                 m_RenderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
165
166                 std::vector<vk::VkImageView> attachments(2);
167                 attachments[0] = *m_AttachmentView;
168                 attachments[1] = *m_DepthView;
169
170                 FramebufferCreateInfo framebufferCreateInfo(*m_RenderPass, attachments, WIDTH, HEIGHT, 1);
171                 m_Framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
172         }
173
174         {
175                 // Pipeline
176
177                 vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
178                 vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
179
180                 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
181
182                 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
183                 m_PipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
184
185                 const vk::VkVertexInputBindingDescription vf_binding_desc               =
186                 {
187                         0,                                                                                                                              // binding;
188                         4 * sizeof(float),                                                                                              // stride;
189                         vk::VK_VERTEX_INPUT_RATE_VERTEX                                                                 // inputRate
190                 };
191
192                 const vk::VkVertexInputAttributeDescription vf_attribute_desc   =
193                 {
194                         0,                                                                                                                              // location;
195                         0,                                                                                                                              // binding;
196                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,                                                              // format;
197                         0                                                                                                                               // offset;
198                 };
199
200                 const vk::VkPipelineVertexInputStateCreateInfo vf_info                  =
201                 {                                                                                                                                       // sType;
202                         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,  // pNext;
203                         NULL,                                                                                                                   // flags;
204                         0u,                                                                                                                             // vertexBindingDescriptionCount;
205                         1,                                                                                                                              // pVertexBindingDescriptions;
206                         &vf_binding_desc,                                                                                               // vertexAttributeDescriptionCount;
207                         1,                                                                                                                              // pVertexAttributeDescriptions;
208                         &vf_attribute_desc
209                 };
210
211                 PipelineCreateInfo pipelineCreateInfo(*m_PipelineLayout, *m_RenderPass, 0, 0);
212                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
213                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
214                 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
215                 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
216                 const vk::VkViewport viewport   =
217                 {
218                         0,              // float x;
219                         0,              // float y;
220                         WIDTH,  // float width;
221                         HEIGHT, // float height;
222                         0.0f,   // float minDepth;
223                         1.0f    // float maxDepth;
224                 };
225
226                 const vk::VkRect2D scissor              =
227                 {
228                         {
229                                 0,              // deInt32 x
230                                 0,              // deInt32 y
231                         },              // VkOffset2D   offset;
232                         {
233                                 WIDTH,  // deInt32 width;
234                                 HEIGHT, // deInt32 height
235                         },              // VkExtent2D   extent;
236                 };
237                 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
238                 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
239                 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
240                 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
241                 pipelineCreateInfo.addState(vf_info);
242                 m_Pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
243         }
244
245         {
246                 // Vertex buffer
247                 const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
248                 m_VertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
249         }
250 }
251
252 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
253 {
254         const vk::VkDevice device                       = m_context.getDevice();
255
256         tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_VertexBuffer->getBoundMemory().getHostPtr());
257         std::copy(vertices.begin(), vertices.end(), ptr);
258
259         vk::flushMappedMemoryRange(vk, device,  m_VertexBuffer->getBoundMemory().getMemory(), m_VertexBuffer->getBoundMemory().getOffset(),     vertices.size() * sizeof(vertices[0]));
260 }
261
262 enum OcclusionQueryResultSize
263 {
264         RESULT_SIZE_64_BIT,
265         RESULT_SIZE_32_BIT,
266 };
267
268 enum OcclusionQueryWait
269 {
270         WAIT_QUEUE,
271         WAIT_QUERY,
272         WAIT_NONE
273 };
274
275 enum OcclusionQueryResultsMode
276 {
277         RESULTS_MODE_GET,
278         RESULTS_MODE_COPY
279 };
280
281 struct OcclusionQueryTestVector
282 {
283         vk::VkQueryControlFlags         queryControlFlags;
284         OcclusionQueryResultSize        queryResultSize;
285         OcclusionQueryWait                      queryWait;
286         OcclusionQueryResultsMode       queryResultsMode;
287         vk::VkDeviceSize                        queryResultsStride;
288         bool                                            queryResultsAvailability;
289         vk::VkPrimitiveTopology         primitiveRopology;
290 };
291
292 class BasicOcclusionQueryTestInstance : public vkt::TestInstance
293 {
294 public:
295                                         BasicOcclusionQueryTestInstance         (vkt::Context &context, const OcclusionQueryTestVector&  testVector);
296                                         ~BasicOcclusionQueryTestInstance        (void);
297 private:
298         tcu::TestStatus iterate                                                         (void);
299
300         enum 
301         {
302                 NUM_QUERIES_IN_POOL                             = 2,\r
303                 QUERY_INDEX_CAPTURE_EMPTY               = 0,\r
304                 QUERY_INDEX_CAPTURE_DRAWCALL    = 1,\r
305                 NUM_VERTICES_IN_DRAWCALL                = 3
306         };
307
308         OcclusionQueryTestVector        m_testVector;
309         StateObjects*                           m_stateObjects;
310         vk::VkQueryPool                         m_queryPool;
311 };
312
313 BasicOcclusionQueryTestInstance::BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector&  testVector)
314         : TestInstance          (context)
315         , m_testVector          (testVector)
316         , m_stateObjects        (new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, m_testVector.primitiveRopology))
317 {
318         DE_ASSERT(testVector.queryResultSize                    == RESULT_SIZE_64_BIT
319                         && testVector.queryWait                                 == WAIT_QUEUE
320                         && testVector.queryResultsMode                  == RESULTS_MODE_GET
321                         && testVector.queryResultsStride                == sizeof(deUint64)
322                         && testVector.queryResultsAvailability  == false
323                         && testVector.primitiveRopology                 == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
324
325         tcu::TestLog&                           log             = m_context.getTestContext().getLog();
326         const vk::VkDevice                      device  = m_context.getDevice();
327         const vk::DeviceInterface&      vk              = m_context.getDeviceInterface();
328
329         const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
330         {
331                 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
332                 DE_NULL,
333                 0u,
334                 vk::VK_QUERY_TYPE_OCCLUSION,
335                 NUM_QUERIES_IN_POOL,
336                 0
337         };
338         VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
339
340         std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
341         vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
342         vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
343         vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
344         m_stateObjects->setVertices(vk, vertices);
345 }
346
347 BasicOcclusionQueryTestInstance::~BasicOcclusionQueryTestInstance (void)
348 {
349         if (m_stateObjects)
350                 delete m_stateObjects;
351
352         if (m_queryPool != DE_NULL)
353         {
354                 const vk::VkDevice device               = m_context.getDevice();
355                 const vk::DeviceInterface& vk   = m_context.getDeviceInterface();
356
357                 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
358         }
359 }
360
361 tcu::TestStatus BasicOcclusionQueryTestInstance::iterate (void)
362 {
363         tcu::TestLog &log                               = m_context.getTestContext().getLog();
364         const vk::VkDevice device               = m_context.getDevice();
365         const vk::VkQueue queue                 = m_context.getUniversalQueue();
366         const vk::DeviceInterface& vk   = m_context.getDeviceInterface();
367
368         const CmdPoolCreateInfo                 cmdPoolCreateInfo       (m_context.getUniversalQueueFamilyIndex());
369         vk::Move<vk::VkCommandPool>             cmdPool                         = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
370
371         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
372         {
373                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
374                 DE_NULL,                                                                                        // const void*                          pNext;
375                 *cmdPool,                                                                                       // VkCommandPool                        commandPool;
376                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
377                 1u,                                                                                                     // deUint32                                     bufferCount;
378         };
379         vk::Unique<vk::VkCommandBuffer> cmdBuffer                       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
380         const CmdBufferBeginInfo                beginInfo                       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
381
382         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
383
384         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
385         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
386
387         std::vector<vk::VkClearValue> renderPassClearValues(2);
388         deMemset(&renderPassClearValues[0], static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue), 0);
389
390         const vk::VkRect2D renderArea =
391         {
392                 { 0,                                    0 },
393                 { StateObjects::WIDTH,  StateObjects::HEIGHT }
394         };
395
396         RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_RenderPass, *m_stateObjects->m_Framebuffer, renderArea, renderPassClearValues);
397
398         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
399
400         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_Pipeline);
401
402         vk::VkBuffer vertexBuffer = m_stateObjects->m_VertexBuffer->object();
403         const vk::VkDeviceSize vertexBufferOffset = 0;
404         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
405
406         vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
407
408         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY, m_testVector.queryControlFlags);
409         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY);
410
411         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL, m_testVector.queryControlFlags);
412         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
413         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL);
414
415         vk.cmdEndRenderPass(*cmdBuffer);
416
417         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
418
419         vk.endCommandBuffer(*cmdBuffer);
420
421         // Submit command buffer
422         const vk::VkSubmitInfo submitInfo =
423         {
424                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
425                 DE_NULL,                                                        // const void*                          pNext;
426                 0,                                                                      // deUint32                                     waitSemaphoreCount;
427                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
428                 1,                                                                      // deUint32                                     commandBufferCount;
429                 &cmdBuffer.get(),                                       // const VkCommandBuffer*       pCommandBuffers;
430                 0,                                                                      // deUint32                                     signalSemaphoreCount;
431                 DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
432         };
433         vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
434
435         VK_CHECK(vk.queueWaitIdle(queue));
436
437         deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
438         size_t queryResultsSize         = sizeof(queryResults);
439
440         vk::VkResult queryResult        = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
441
442         if (queryResult == vk::VK_NOT_READY)
443         {
444                 TCU_FAIL("Query result not avaliable, but vkWaitIdle() was called.");
445         }
446
447         VK_CHECK(queryResult);
448
449         log << tcu::TestLog::Section("OcclusionQueryResults",
450                 "Occlusion query results");
451         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
452         {
453                 log << tcu::TestLog::Message << "query[ slot == " << ndx
454                         << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
455         }
456
457         bool passed = true;
458         
459         for (int queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
460         {
461
462                 deUint64 expectedValue;
463
464                 switch (queryNdx)
465                 {
466                         case QUERY_INDEX_CAPTURE_EMPTY:
467                                 expectedValue = 0;
468                                 break;
469                         case QUERY_INDEX_CAPTURE_DRAWCALL:
470                                 expectedValue = NUM_VERTICES_IN_DRAWCALL;
471                                 break;
472                 }
473
474                 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || expectedValue == 0)
475                 {
476                         // require precise value
477                         if (queryResults[queryNdx] != expectedValue)
478                         {
479                                 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
480                                         "wrong value of query for index "
481                                         << queryNdx << ", expected " << expectedValue << ", got "
482                                         << queryResults[0] << "." << tcu::TestLog::EndMessage;
483                                 passed = false;
484                         }
485                 }
486                 else
487                 {
488                         // require imprecize value > 0
489                         if (queryResults[queryNdx] == 0)
490                         {
491                                 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
492                                         "wrong value of query for index "
493                                         << queryNdx << ", expected any non-zero value, got "
494                                         << queryResults[0] << "." << tcu::TestLog::EndMessage;
495                                 passed = false;
496                         }
497                 }
498         }
499         log << tcu::TestLog::EndSection;
500
501         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
502
503         tcu::ConstPixelBufferAccess resultImageAccess = m_stateObjects->m_ColorAttachmentImage->readSurface(
504                                 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
505                                 zeroOffset,  StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
506
507         log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
508
509         if (passed)
510         {
511                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
512         }
513         return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
514 }
515
516 class OcclusionQueryTestInstance : public vkt::TestInstance
517 {
518 public:
519         OcclusionQueryTestInstance              (vkt::Context &context, const OcclusionQueryTestVector& testVector);
520         ~OcclusionQueryTestInstance             (void);
521 private:
522         tcu::TestStatus                                 iterate                                                 (void);
523
524         vk::Move<vk::VkCommandBuffer>   recordRender                                    (vk::VkCommandPool commandPool);
525         vk::Move<vk::VkCommandBuffer>   recordCopyResults                               (vk::VkCommandPool commandPool);
526
527         void                                                    captureResults                                  (deUint64*                      retResults,     deUint64*               retAvailability,        bool    allowNotReady);
528         void                                                    logResults                                              (const deUint64*        results,        const deUint64* availability);
529         bool                                                    validateResults                                 (const deUint64*        results,        const deUint64* availability,           bool    allowUnavailable,       vk::VkPrimitiveTopology primitiveTopology);
530         void                                                    logRenderTarget                                 (void);
531
532         enum 
533         {
534                 NUM_QUERIES_IN_POOL                                                     = 3,\r
535                 QUERY_INDEX_CAPTURE_ALL                                         = 0,\r
536                 QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED          = 1,\r
537                 QUERY_INDEX_CAPTURE_OCCLUDED                            = 2
538         };
539         enum
540         {
541                 NUM_VERTICES_IN_DRAWCALL                                        = 3,\r
542                 NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL     = 3,\r
543                 NUM_VERTICES_IN_OCCLUDER_DRAWCALL                       = 3,\r
544                 NUM_VERTICES                                                            = NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL\r
545         };\r
546         enum\r
547         {\r
548                 START_VERTEX                                                            = 0,\r
549                 START_VERTEX_PARTIALLY_OCCLUDED                         = START_VERTEX + NUM_VERTICES_IN_DRAWCALL,\r
550                 START_VERTEX_OCCLUDER                                           = START_VERTEX_PARTIALLY_OCCLUDED + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL
551         };
552
553         OcclusionQueryTestVector                m_testVector;
554
555         const vk::VkQueryResultFlags    m_queryResultFlags;
556
557         StateObjects*                                   m_stateObjects;
558         vk::VkQueryPool                                 m_queryPool;
559         de::SharedPtr<Buffer>                   m_queryPoolResultsBuffer;
560
561         vk::Move<vk::VkCommandPool>             m_commandPool;
562         vk::Move<vk::VkCommandBuffer>   m_renderCommandBuffer;
563         vk::Move<vk::VkCommandBuffer>   m_copyResultsCommandBuffer;
564 };
565
566 OcclusionQueryTestInstance::OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
567         : vkt::TestInstance             (context)
568         , m_testVector                  (testVector)
569         , m_stateObjects                (new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL, m_testVector.primitiveRopology))
570         , m_queryResultFlags    ((m_testVector.queryWait == WAIT_QUERY                                  ? vk::VK_QUERY_RESULT_WAIT_BIT                          : 0)
571                                                         | (m_testVector.queryResultSize == RESULT_SIZE_64_BIT   ? vk::VK_QUERY_RESULT_64_BIT                            : 0)
572                                                         | (m_testVector.queryResultsAvailability                                ? vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT     : 0))
573 {
574         const vk::VkDevice                      device                          = m_context.getDevice();
575         const vk::DeviceInterface&      vk                                      = m_context.getDeviceInterface();
576
577         const vk::VkQueryPoolCreateInfo queryPoolCreateInfo     =
578         {
579                 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
580                 DE_NULL,
581                 0u,
582                 vk::VK_QUERY_TYPE_OCCLUSION,
583                 NUM_QUERIES_IN_POOL,
584                 0
585         };
586
587         VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
588
589         if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
590         {
591                 const vk::VkDeviceSize  resultsBufferSize                       = m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL;
592                                                                 m_queryPoolResultsBuffer        = Buffer::createAndAlloc(vk, device, BufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
593         }
594
595         const CmdPoolCreateInfo cmdPoolCreateInfo               (m_context.getUniversalQueueFamilyIndex());
596                                                         m_commandPool                   = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
597                                                         m_renderCommandBuffer   = recordRender(*m_commandPool);
598
599         if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
600         {
601                 m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
602         }
603 }
604
605 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
606 {
607         const vk::VkDevice device = m_context.getDevice();
608
609         if (m_stateObjects)
610                 delete m_stateObjects;
611
612         if (m_queryPool != DE_NULL)
613         {
614                 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
615                 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
616         }
617 }
618
619 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
620 {
621         const vk::VkDevice                      device          = m_context.getDevice();
622         const vk::VkQueue                       queue           = m_context.getUniversalQueue();
623         const vk::DeviceInterface&      vk                      = m_context.getDeviceInterface();
624         tcu::TestLog&                           log                     = m_context.getTestContext().getLog();
625         std::vector<tcu::Vec4>          vertices        (NUM_VERTICES);
626
627         // 1st triangle
628         vertices[START_VERTEX + 0] = tcu::Vec4( 0.5,  0.5, 0.5, 1.0);
629         vertices[START_VERTEX + 1] = tcu::Vec4( 0.5, -0.5, 0.5, 1.0);
630         vertices[START_VERTEX + 2] = tcu::Vec4(-0.5,  0.5, 0.5, 1.0);
631         // 2nd triangle - partially occluding the scene
632         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 0] = tcu::Vec4(-0.5, -0.5, 1.0, 1.0);
633         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
634         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
635         // 3nd triangle - fully occluding the scene
636         vertices[START_VERTEX_OCCLUDER + 0] = tcu::Vec4( 0.5,  0.5, 1.0, 1.0);
637         vertices[START_VERTEX_OCCLUDER + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
638         vertices[START_VERTEX_OCCLUDER + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
639
640         m_stateObjects->setVertices(vk, vertices);
641
642         const vk::VkSubmitInfo submitInfo =
643         {
644                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
645                 DE_NULL,                                                        // const void*                          pNext;
646                 0,                                                                      // deUint32                                     waitSemaphoreCount;
647                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
648                 1,                                                                      // deUint32                                     commandBufferCount;
649                 &m_renderCommandBuffer.get(),           // const VkCommandBuffer*       pCommandBuffers;
650                 0,                                                                      // deUint32                                     signalSemaphoreCount;
651                 DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
652         };
653         vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
654
655         if (m_testVector.queryWait == WAIT_QUEUE)
656         {
657                 VK_CHECK(vk.queueWaitIdle(queue));
658
659                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
660                 {
661                         // In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
662                         // contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
663                         
664                         // In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
665
666                         const vk::VkSubmitInfo submitInfo =
667                         {
668                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
669                                 DE_NULL,                                                        // const void*                          pNext;
670                                 0,                                                                      // deUint32                                     waitSemaphoreCount;
671                                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
672                                 1,                                                                      // deUint32                                     commandBufferCount;
673                                 &m_copyResultsCommandBuffer.get(),      // const VkCommandBuffer*       pCommandBuffers;
674                                 0,                                                                      // deUint32                                     signalSemaphoreCount;
675                                 DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
676                         };
677                         vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
678                 }
679         }
680
681         if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
682         {
683                 // In case of vkCmdCopyQueryResults is used, test must always wait for it
684                 // to complete before we can read the result buffer.
685
686                 VK_CHECK(vk.queueWaitIdle(queue));
687         }
688
689         deUint64 queryResults           [NUM_QUERIES_IN_POOL];
690         deUint64 queryAvailability      [NUM_QUERIES_IN_POOL];
691
692         // Allow not ready results only if nobody waited before getting the query results
693         bool    allowNotReady           = (m_testVector.queryWait == WAIT_NONE);
694
695         captureResults(queryResults, queryAvailability, allowNotReady);
696
697         log << tcu::TestLog::Section("OcclusionQueryResults", "Occlusion query results");
698
699         logResults(queryResults, queryAvailability);
700         bool passed = validateResults(queryResults, queryAvailability, allowNotReady, m_testVector.primitiveRopology);
701
702         log << tcu::TestLog::EndSection;
703
704         logRenderTarget();
705
706                 if (passed)
707         {
708                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
709         }
710         return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
711 }
712
713 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordRender (vk::VkCommandPool cmdPool)
714 {
715         const vk::VkDevice                              device          = m_context.getDevice();
716         const vk::VkQueue                               queue           = m_context.getUniversalQueue();
717         const vk::DeviceInterface&              vk                      = m_context.getDeviceInterface();
718
719         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
720         {
721                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
722                 DE_NULL,                                                                                        // const void*                          pNext;
723                 cmdPool,                                                                                        // VkCommandPool                        commandPool;
724                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
725                 1u,                                                                                                     // deUint32                                     bufferCount;
726         };
727         vk::Move<vk::VkCommandBuffer>   cmdBuffer       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
728         CmdBufferBeginInfo                              beginInfo       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
729
730         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
731
732         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
733         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
734
735         std::vector<vk::VkClearValue>   renderPassClearValues(2);
736         deMemset(&renderPassClearValues[0], static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue), 0);
737
738         const vk::VkRect2D renderArea = 
739         {
740                 { 0,                                    0 },
741                 { StateObjects::WIDTH,  StateObjects::HEIGHT }
742         };
743
744         RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_RenderPass, *m_stateObjects->m_Framebuffer, renderArea, renderPassClearValues);
745
746         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
747
748         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,     *m_stateObjects->m_Pipeline);
749
750         vk::VkBuffer vertexBuffer = m_stateObjects->m_VertexBuffer->object();
751         const vk::VkDeviceSize vertexBufferOffset = 0;
752         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
753
754         vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
755
756         // Draw un-occluded geometry
757         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL, m_testVector.queryControlFlags);
758         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
759         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL);
760
761         // Partially occlude geometry
762         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL, 1, START_VERTEX_PARTIALLY_OCCLUDED, 0);
763
764         // Draw partially-occluded geometry
765         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED, m_testVector.queryControlFlags);
766         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
767         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED);
768
769         // Occlude geometry
770         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_OCCLUDER_DRAWCALL, 1, START_VERTEX_OCCLUDER, 0);
771
772         // Draw occluded geometry
773         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED, m_testVector.queryControlFlags);
774         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
775         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED);
776
777         if (m_testVector.queryWait != WAIT_QUEUE )
778         {
779                 //For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
780                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
781                 {
782                         vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
783                 }
784         }
785
786         vk.cmdEndRenderPass(*cmdBuffer);
787
788         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
789
790         vk.endCommandBuffer(*cmdBuffer);
791
792         return cmdBuffer;
793 }
794
795 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
796 {
797         const vk::VkDevice                              device          = m_context.getDevice();
798         const vk::VkQueue                               queue           = m_context.getUniversalQueue();
799         const vk::DeviceInterface&              vk                      = m_context.getDeviceInterface();
800
801         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
802         {
803                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
804                 DE_NULL,                                                                                        // const void*                          pNext;
805                 cmdPool,                                                                                        // VkCommandPool                        commandPool;
806                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
807                 1u,                                                                                                     // deUint32                                     bufferCount;
808         };
809         vk::Move<vk::VkCommandBuffer>   cmdBuffer       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
810         const CmdBufferBeginInfo                beginInfo       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
811
812         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
813         vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
814         vk.endCommandBuffer(*cmdBuffer);
815
816         return cmdBuffer;
817 }
818
819 void OcclusionQueryTestInstance::captureResults (deUint64* retResults, deUint64* retAvailAbility, bool allowNotReady)
820 {
821
822         const vk::VkDevice                      device                  = m_context.getDevice();
823         const vk::DeviceInterface&      vk                              = m_context.getDeviceInterface();
824         std::vector<deUint8>            resultsBuffer   (m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL);
825
826         if (m_testVector.queryResultsMode == RESULTS_MODE_GET)
827         {
828                 const vk::VkResult queryResult = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, resultsBuffer.size(), &resultsBuffer[0], m_testVector.queryResultsStride, m_queryResultFlags);
829                 if (queryResult == vk::VK_NOT_READY && !allowNotReady)
830                 {
831                         TCU_FAIL("getQueryPoolResults returned VK_NOT_READY, but results should be already available.");
832                 }
833                 else
834                 {
835                         VK_CHECK(queryResult);
836                 }
837         }
838         else if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
839         {
840                 const vk::Allocation& allocation = m_queryPoolResultsBuffer->getBoundMemory();
841                 const void* allocationData = allocation.getHostPtr();
842
843                 vk::invalidateMappedMemoryRange(vk, device, allocation.getMemory(), allocation.getOffset(), resultsBuffer.size());
844
845                 deMemcpy(&resultsBuffer[0], allocationData, resultsBuffer.size());
846         }
847
848         for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; queryNdx++)
849         {
850                 const void* srcPtr = &resultsBuffer[queryNdx * m_testVector.queryResultsStride];
851                 if (m_testVector.queryResultSize == RESULT_SIZE_32_BIT)
852                 {
853                         const deUint32* srcPtrTyped = static_cast<const deUint32*>(srcPtr);
854                         retResults[queryNdx]            = *srcPtrTyped;
855                         if (m_testVector.queryResultsAvailability)
856                         {
857                                 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
858                         }
859                 }
860                 else if (m_testVector.queryResultSize == RESULT_SIZE_64_BIT)
861                 {
862                         const deUint64* srcPtrTyped = static_cast<const deUint64*>(srcPtr);
863                         retResults[queryNdx]            = *srcPtrTyped;
864
865                         if (m_testVector.queryResultsAvailability)
866                         {
867                                 if (m_testVector.queryResultsAvailability)
868                                 {
869                                         retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
870                                 }
871                         }
872                 }
873                 else
874                 {
875                         TCU_FAIL("Wrong m_testVector.queryResultSize");
876                 }
877         }
878 }
879
880 void OcclusionQueryTestInstance::logResults (const deUint64* results, const deUint64* availability)
881 {
882         tcu::TestLog& log = m_context.getTestContext().getLog();
883
884         for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
885         {
886                 if (!m_testVector.queryResultsAvailability)
887                 {
888                         log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << tcu::TestLog::EndMessage;
889                 }
890                 else
891                 {
892                         log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << ", availability   == " << availability[ndx] << tcu::TestLog::EndMessage;
893                 }
894         }
895 }
896
897 bool OcclusionQueryTestInstance::validateResults (const deUint64* results , const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology)
898 {
899         bool passed                     = true;
900         tcu::TestLog& log       = m_context.getTestContext().getLog();
901
902         for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
903         {
904                 deUint64 expectedValueMin = 0;
905                 deUint64 expectedValueMax = 0;
906
907                 if (m_testVector.queryResultsAvailability && availability[queryNdx] == 0)
908                 {
909                         // query result was not available
910                         if (!allowUnavailable)
911                         {
912                                 log << tcu::TestLog::Message << "query results availability was 0 for index "
913                                         << queryNdx << ", expected any value greater than 0." << tcu::TestLog::EndMessage;
914                                 passed = false;
915                                 continue;
916                         }
917                 }
918                 else
919                 {
920                         // query is available, so expect proper result values
921                         if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
922                         {
923                                 switch (queryNdx)
924                                 {
925                                         case QUERY_INDEX_CAPTURE_OCCLUDED:
926                                                 expectedValueMin = 0;
927                                                 expectedValueMax = 0;
928                                                 break;
929                                         case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
930                                                 expectedValueMin = 1;
931                                                 expectedValueMax = 1;
932                                                 break;
933                                         case QUERY_INDEX_CAPTURE_ALL:
934                                                 expectedValueMin = NUM_VERTICES_IN_DRAWCALL;
935                                                 expectedValueMax = NUM_VERTICES_IN_DRAWCALL;
936                                                 break;
937                                 }
938                         }
939                         else if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
940                         {
941                                 switch (queryNdx)
942                                 {
943                                         case QUERY_INDEX_CAPTURE_OCCLUDED:
944                                                 expectedValueMin = 0;
945                                                 expectedValueMax = 0;
946                                                 break;
947                                         case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
948                                         case QUERY_INDEX_CAPTURE_ALL:
949                                                 {
950                                                         const int primWidth             = StateObjects::WIDTH  / 2;
951                                                         const int primHeight    = StateObjects::HEIGHT / 2;
952                                                         const int primArea              = primWidth * primHeight / 2;
953                                                         expectedValueMin                = (int)(0.97f * primArea);
954                                                         expectedValueMax                = (int)(1.03f * primArea);
955                                                 }
956                                 }
957                         }
958                         else
959                         {
960                                 TCU_FAIL("Unsupported primitive topology");
961                         }
962                 }
963
964                 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || (expectedValueMin == 0 && expectedValueMax == 0))
965                 {
966                         // require precise value
967                         if (results[queryNdx] < expectedValueMin || results[queryNdx] > expectedValueMax)
968                         {
969                                 log << tcu::TestLog::Message << "wrong value of query for index "
970                                         << queryNdx << ", expected the value minimum of " << expectedValueMin << ", maximum of " << expectedValueMax << " got "
971                                         << results[queryNdx] << "." << tcu::TestLog::EndMessage;
972                                 passed = false;
973                         }
974                 }
975                 else
976                 {
977                         // require imprecise value greater than 0
978                         if (results[queryNdx] == 0)
979                         {
980                                 log << tcu::TestLog::Message << "wrong value of query for index "
981                                         << queryNdx << ", expected any non-zero value, got "
982                                         << results[queryNdx] << "." << tcu::TestLog::EndMessage;
983                                 passed = false;
984                         }
985                 }
986         }
987         return passed;
988 }
989
990 void OcclusionQueryTestInstance::logRenderTarget (void)
991 {
992         tcu::TestLog&                   log                                             = m_context.getTestContext().getLog();
993         const vk::VkQueue               queue                                   = m_context.getUniversalQueue();
994         const vk::VkOffset3D    zeroOffset                              = { 0, 0, 0 };
995         tcu::ConstPixelBufferAccess resultImageAccess   = m_stateObjects->m_ColorAttachmentImage->readSurface(
996                 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
997                 zeroOffset, StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
998
999         log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
1000 }
1001
1002 template<class Instance>
1003 class QueryPoolOcclusionTest : public vkt::TestCase
1004 {
1005 public:
1006         QueryPoolOcclusionTest (tcu::TestContext &context, const char *name, const char *description, const OcclusionQueryTestVector& testVector)
1007                 : TestCase                      (context, name, description)
1008                 , m_testVector          (testVector)
1009         {
1010         }
1011 private:
1012         vkt::TestInstance* createInstance (vkt::Context& context) const
1013         {
1014                 return new Instance(context, m_testVector);
1015         }
1016
1017         void initPrograms(vk::SourceCollections& programCollection) const
1018         {
1019                 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 400\n"
1020                                                                                                                                            "layout(location = 0) out vec4 out_FragColor;\n"
1021                                                                                                                                            "void main()\n"
1022                                                                                                                                            "{\n"
1023                                                                                                                                            "    out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
1024                                                                                                                                            "}\n");
1025
1026                 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
1027                                                                                                                                                  "layout(location = 0) in vec4 in_Postion;\n"
1028                                                                                                                                                  "void main() {\n"
1029                                                                                                                                                  "      gl_Position  = in_Postion;\n"
1030                                                                                                                                                  "      gl_PointSize = 1.0;\n"
1031                                                                                                                                                  "}\n");
1032         }
1033
1034         OcclusionQueryTestVector m_testVector;
1035 };
1036
1037 } //anonymous
1038
1039 namespace vkt
1040 {
1041
1042 namespace QueryPool
1043 {
1044
1045 QueryPoolOcclusionTests::QueryPoolOcclusionTests (tcu::TestContext &testCtx)
1046         : TestCaseGroup(testCtx, "occlusion_query", "Tests for occlusion queries")
1047 {
1048         /* Left blank on purpose */
1049 }
1050
1051 QueryPoolOcclusionTests::~QueryPoolOcclusionTests (void)
1052 {
1053         /* Left blank on purpose */
1054 }
1055
1056 void QueryPoolOcclusionTests::init (void)
1057 {
1058         OcclusionQueryTestVector baseTestVector;
1059         baseTestVector.queryControlFlags                = 0;
1060         baseTestVector.queryResultSize                  = RESULT_SIZE_64_BIT;
1061         baseTestVector.queryWait                                = WAIT_QUEUE;
1062         baseTestVector.queryResultsMode                 = RESULTS_MODE_GET;
1063         baseTestVector.queryResultsStride               = sizeof(deUint64);
1064         baseTestVector.queryResultsAvailability = false;
1065         baseTestVector.primitiveRopology                = vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1066
1067         //Basic tests
1068         {
1069                 OcclusionQueryTestVector testVector = baseTestVector;
1070                 testVector.queryControlFlags = 0;
1071                 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_conservative",   "draw with conservative occlusion query",       testVector));
1072                 testVector.queryControlFlags = vk::VK_QUERY_CONTROL_PRECISE_BIT;
1073                 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_precise",                "draw with precise occlusion query",            testVector));
1074         }
1075
1076         // Functional test
1077         {
1078                 vk::VkQueryControlFlags controlFlags[]          = { 0,                                  vk::VK_QUERY_CONTROL_PRECISE_BIT        };
1079                 const char*                             controlFlagsStr[]       = { "conservative",             "precise"                                                       };
1080
1081                 for (int controlFlagIdx = 0; controlFlagIdx < DE_LENGTH_OF_ARRAY(controlFlags); ++controlFlagIdx)
1082                 {
1083
1084                         vk::VkPrimitiveTopology primitiveTopology[]             = { vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST };
1085                         const char*                             primitiveTopologyStr[]  = { "points", "triangles" };
1086                         for (int primitiveTopologyIdx = 0; primitiveTopologyIdx < DE_LENGTH_OF_ARRAY(primitiveTopology); ++primitiveTopologyIdx)
1087                         {
1088
1089                                 OcclusionQueryResultSize        resultSize[]    = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1090                                 const char*                                     resultSizeStr[] = { "32",                               "64" };
1091
1092                                 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSize); ++resultSizeIdx)
1093                                 {
1094
1095                                         OcclusionQueryWait      wait[]          = { WAIT_QUEUE, WAIT_QUERY };
1096                                         const char*                     waitStr[]       = { "queue",    "query" };
1097
1098                                         for (int waitIdx = 0; waitIdx < DE_LENGTH_OF_ARRAY(wait); ++waitIdx)
1099                                         {
1100                                                 OcclusionQueryResultsMode       resultsMode[]           = { RESULTS_MODE_GET,   RESULTS_MODE_COPY };
1101                                                 const char*                                     resultsModeStr[]        = { "get",                              "copy" };
1102
1103                                                 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1104                                                 {
1105
1106                                                         bool testAvailability[]                         = { false, true };
1107                                                         const char* testAvailabilityStr[]       = { "without", "with"};
1108
1109                                                         for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1110                                                         {
1111                                                                 OcclusionQueryTestVector testVector                     = baseTestVector;
1112                                                                 testVector.queryControlFlags                            = controlFlags[controlFlagIdx];
1113                                                                 testVector.queryResultSize                                      = resultSize[resultSizeIdx];
1114                                                                 testVector.queryWait                                            = wait[waitIdx];
1115                                                                 testVector.queryResultsMode                                     = resultsMode[resultsModeIdx];
1116                                                                 testVector.queryResultsStride                           = (testVector.queryResultSize == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1117                                                                 testVector.queryResultsAvailability                     = testAvailability[testAvailabilityIdx];
1118                                                                 testVector.primitiveRopology                            = primitiveTopology[primitiveTopologyIdx];
1119
1120                                                                 if (testVector.queryResultsAvailability)
1121                                                                 {
1122                                                                         testVector.queryResultsStride *= 2;
1123                                                                 }
1124
1125                                                                 std::ostringstream testName;
1126                                                                 std::ostringstream testDescr;
1127
1128                                                                 testName << resultsModeStr[resultsModeIdx] << "_results"
1129                                                                                  << "_" << controlFlagsStr[controlFlagIdx]
1130                                                                                  << "_size_" << resultSizeStr[resultSizeIdx]
1131                                                                                  << "_wait_" << waitStr[waitIdx]
1132                                                                                  << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability"
1133                                                                                  << "_draw_" <<  primitiveTopologyStr[primitiveTopologyIdx];
1134
1135                                                                 testDescr << "draw occluded " << primitiveTopologyStr[primitiveTopologyIdx]
1136                                                                                   << "with " << controlFlagsStr[controlFlagIdx] << ", "
1137                                                                               << resultsModeStr[resultsModeIdx] << " results "
1138                                                                               << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1139                                                                                   << resultSizeStr[resultSizeIdx] << "bit variables,"
1140                                                                               << "wait for results on" << waitStr[waitIdx];
1141
1142                                                                 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1143                                                         }
1144                                                 }
1145                                         }
1146                                 }
1147                         }
1148                 }
1149         }
1150         // Test different strides
1151         {
1152                 OcclusionQueryResultsMode       resultsMode[]           = { RESULTS_MODE_GET,   RESULTS_MODE_COPY       };
1153                 const char*                                     resultsModeStr[]        = { "get",                              "copy"                          };
1154
1155                 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1156                 {
1157                         OcclusionQueryResultSize        resultSizes[]   = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1158                         const char*                                     resultSizeStr[] = { "32", "64" };
1159
1160                         bool testAvailability[]                         = { false,              true    };
1161                         const char* testAvailabilityStr[]       = { "without",  "with"  };
1162
1163                         for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1164                         {
1165                                 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSizes); ++resultSizeIdx)
1166                                 {
1167                                         const vk::VkDeviceSize resultSize       = (resultSizes[resultSizeIdx] == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1168
1169                                         // \todo [2015-12-18 scygan] Ensure only stride values aligned to resultSize are allowed. Otherwise test should be extended.
1170                                         const vk::VkDeviceSize strides[]        =
1171                                         {
1172                                                 1 * resultSize,
1173                                                 2 * resultSize,
1174                                                 3 * resultSize,
1175                                                 4 * resultSize,
1176                                                 5 * resultSize,
1177                                                 13 * resultSize,
1178                                                 1024 * resultSize
1179                                         };
1180
1181                                         for (int strideIdx = 0; strideIdx < DE_LENGTH_OF_ARRAY(strides); strideIdx++)
1182                                         {
1183                                                 OcclusionQueryTestVector testVector             = baseTestVector;
1184                                                 testVector.queryResultsMode                             = resultsMode[resultsModeIdx];
1185                                                 testVector.queryResultSize                              = resultSizes[resultSizeIdx];
1186                                                 testVector.queryResultsAvailability             = testAvailability[testAvailabilityIdx];
1187                                                 testVector.queryResultsStride                   = strides[strideIdx];
1188
1189                                                 const vk::VkDeviceSize elementSize              = (testVector.queryResultsAvailability ? resultSize * 2 : resultSize);
1190
1191                                                 if (elementSize > testVector.queryResultsStride)
1192                                                 {
1193                                                         continue;
1194                                                 }
1195
1196                                                 std::ostringstream testName;
1197                                                 std::ostringstream testDescr;
1198
1199                                                 testName << resultsModeStr[resultsModeIdx]
1200                                                                  << "_results_size_" << resultSizeStr[resultSizeIdx]
1201                                                                  << "_stride_" << strides[strideIdx]
1202                                                                  << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability";
1203
1204                                                 testDescr << resultsModeStr[resultsModeIdx] << " results "
1205                                                                   << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1206                                                                   << resultSizeStr[resultSizeIdx] << "bit variables, with stride" << strides[strideIdx];
1207
1208                                                 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1209                                         }
1210                                 }
1211                         }
1212                 }
1213
1214         }
1215 }
1216
1217 } //QueryPool
1218 } //vkt
1219