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