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