Bug Fix: Corrected barriers in the tests dEQP-VK.query_pool
[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_GENERAL, 0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
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, 0, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
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_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
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         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
496
497         tcu::ConstPixelBufferAccess resultImageAccess = m_stateObjects->m_colorAttachmentImage->readSurface(
498                                 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
499                                 zeroOffset,  StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
500
501         log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
502
503         if (passed)
504         {
505                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
506         }
507         return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
508 }
509
510 class OcclusionQueryTestInstance : public vkt::TestInstance
511 {
512 public:
513         OcclusionQueryTestInstance              (vkt::Context &context, const OcclusionQueryTestVector& testVector);
514         ~OcclusionQueryTestInstance             (void);
515 private:
516         tcu::TestStatus                                 iterate                                                 (void);
517
518         vk::Move<vk::VkCommandBuffer>   recordRender                                    (vk::VkCommandPool commandPool);
519         vk::Move<vk::VkCommandBuffer>   recordCopyResults                               (vk::VkCommandPool commandPool);
520
521         void                                                    captureResults                                  (deUint64*                      retResults,     deUint64*               retAvailability,        bool    allowNotReady);
522         void                                                    logResults                                              (const deUint64*        results,        const deUint64* availability);
523         bool                                                    validateResults                                 (const deUint64*        results,        const deUint64* availability,           bool    allowUnavailable,       vk::VkPrimitiveTopology primitiveTopology);
524         void                                                    logRenderTarget                                 (void);
525
526         enum
527         {
528                 NUM_QUERIES_IN_POOL                                                     = 3,
529                 QUERY_INDEX_CAPTURE_ALL                                         = 0,
530                 QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED          = 1,
531                 QUERY_INDEX_CAPTURE_OCCLUDED                            = 2
532         };
533         enum
534         {
535                 NUM_VERTICES_IN_DRAWCALL                                        = 3,
536                 NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL     = 3,
537                 NUM_VERTICES_IN_OCCLUDER_DRAWCALL                       = 3,
538                 NUM_VERTICES                                                            = NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL
539         };
540         enum
541         {
542                 START_VERTEX                                                            = 0,
543                 START_VERTEX_PARTIALLY_OCCLUDED                         = START_VERTEX + NUM_VERTICES_IN_DRAWCALL,
544                 START_VERTEX_OCCLUDER                                           = START_VERTEX_PARTIALLY_OCCLUDED + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL
545         };
546
547         OcclusionQueryTestVector                m_testVector;
548
549         const vk::VkQueryResultFlags    m_queryResultFlags;
550
551         StateObjects*                                   m_stateObjects;
552         vk::VkQueryPool                                 m_queryPool;
553         de::SharedPtr<Buffer>                   m_queryPoolResultsBuffer;
554
555         vk::Move<vk::VkCommandPool>             m_commandPool;
556         vk::Move<vk::VkCommandBuffer>   m_renderCommandBuffer;
557         vk::Move<vk::VkCommandBuffer>   m_copyResultsCommandBuffer;
558 };
559
560 OcclusionQueryTestInstance::OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
561         : vkt::TestInstance             (context)
562         , m_testVector                  (testVector)
563         , m_queryResultFlags    ((m_testVector.queryWait == WAIT_QUERY                                  ? vk::VK_QUERY_RESULT_WAIT_BIT                          : 0)
564                                                         | (m_testVector.queryResultSize == RESULT_SIZE_64_BIT   ? vk::VK_QUERY_RESULT_64_BIT                            : 0)
565                                                         | (m_testVector.queryResultsAvailability                                ? vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT     : 0))
566 {
567         const vk::VkDevice                      device                          = m_context.getDevice();
568         const vk::DeviceInterface&      vk                                      = m_context.getDeviceInterface();
569
570         if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) && !m_context.getDeviceFeatures().occlusionQueryPrecise)
571                 throw tcu::NotSupportedError("Precise occlusion queries are not supported");
572
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.primitiveTopology);
574
575         const vk::VkQueryPoolCreateInfo queryPoolCreateInfo     =
576         {
577                 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
578                 DE_NULL,
579                 0u,
580                 vk::VK_QUERY_TYPE_OCCLUSION,
581                 NUM_QUERIES_IN_POOL,
582                 0
583         };
584
585         VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
586
587         if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
588         {
589                 const vk::VkDeviceSize  resultsBufferSize                       = m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL;
590                                                                 m_queryPoolResultsBuffer        = Buffer::createAndAlloc(vk, device, BufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
591         }
592
593         const CmdPoolCreateInfo cmdPoolCreateInfo               (m_context.getUniversalQueueFamilyIndex());
594                                                         m_commandPool                   = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
595                                                         m_renderCommandBuffer   = recordRender(*m_commandPool);
596
597         if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
598         {
599                 m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
600         }
601 }
602
603 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
604 {
605         const vk::VkDevice device = m_context.getDevice();
606
607         if (m_stateObjects)
608                 delete m_stateObjects;
609
610         if (m_queryPool != DE_NULL)
611         {
612                 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
613                 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
614         }
615 }
616
617 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
618 {
619         const vk::VkQueue                       queue           = m_context.getUniversalQueue();
620         const vk::DeviceInterface&      vk                      = m_context.getDeviceInterface();
621         tcu::TestLog&                           log                     = m_context.getTestContext().getLog();
622         std::vector<tcu::Vec4>          vertices        (NUM_VERTICES);
623
624         // 1st triangle
625         vertices[START_VERTEX + 0] = tcu::Vec4( 0.5,  0.5, 0.5, 1.0);
626         vertices[START_VERTEX + 1] = tcu::Vec4( 0.5, -0.5, 0.5, 1.0);
627         vertices[START_VERTEX + 2] = tcu::Vec4(-0.5,  0.5, 0.5, 1.0);
628         // 2nd triangle - partially occluding the scene
629         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 0] = tcu::Vec4(-0.5, -0.5, 1.0, 1.0);
630         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
631         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
632         // 3nd triangle - fully occluding the scene
633         vertices[START_VERTEX_OCCLUDER + 0] = tcu::Vec4( 0.5,  0.5, 1.0, 1.0);
634         vertices[START_VERTEX_OCCLUDER + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
635         vertices[START_VERTEX_OCCLUDER + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
636
637         m_stateObjects->setVertices(vk, vertices);
638
639         {
640                 const vk::VkSubmitInfo submitInfo =
641                 {
642                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
643                         DE_NULL,                                                        // const void*                          pNext;
644                         0,                                                                      // deUint32                                     waitSemaphoreCount;
645                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
646                         (const vk::VkPipelineStageFlags*)DE_NULL,
647                         1,                                                                      // deUint32                                     commandBufferCount;
648                         &m_renderCommandBuffer.get(),           // const VkCommandBuffer*       pCommandBuffers;
649                         0,                                                                      // deUint32                                     signalSemaphoreCount;
650                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
651                 };
652                 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
653         }
654
655         if (m_testVector.queryWait == WAIT_QUEUE)
656         {
657                 VK_CHECK(vk.queueWaitIdle(queue));
658
659                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
660                 {
661                         // In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
662                         // contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
663
664                         // In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
665
666                         const vk::VkSubmitInfo submitInfo =
667                         {
668                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
669                                 DE_NULL,                                                        // const void*                          pNext;
670                                 0,                                                                      // deUint32                                     waitSemaphoreCount;
671                                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
672                                 (const vk::VkPipelineStageFlags*)DE_NULL,
673                                 1,                                                                      // deUint32                                     commandBufferCount;
674                                 &m_copyResultsCommandBuffer.get(),      // const VkCommandBuffer*       pCommandBuffers;
675                                 0,                                                                      // deUint32                                     signalSemaphoreCount;
676                                 DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
677                         };
678                         vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
679                 }
680         }
681
682         if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
683         {
684                 // In case of vkCmdCopyQueryResults is used, test must always wait for it
685                 // to complete before we can read the result buffer.
686
687                 VK_CHECK(vk.queueWaitIdle(queue));
688         }
689
690         deUint64 queryResults           [NUM_QUERIES_IN_POOL];
691         deUint64 queryAvailability      [NUM_QUERIES_IN_POOL];
692
693         // Allow not ready results only if nobody waited before getting the query results
694         bool    allowNotReady           = (m_testVector.queryWait == WAIT_NONE);
695
696         captureResults(queryResults, queryAvailability, allowNotReady);
697
698         log << tcu::TestLog::Section("OcclusionQueryResults", "Occlusion query results");
699
700         logResults(queryResults, queryAvailability);
701         bool passed = validateResults(queryResults, queryAvailability, allowNotReady, m_testVector.primitiveTopology);
702
703         log << tcu::TestLog::EndSection;
704
705         logRenderTarget();
706
707                 if (passed)
708         {
709                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
710         }
711         return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
712 }
713
714 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordRender (vk::VkCommandPool cmdPool)
715 {
716         const vk::VkDevice                              device          = m_context.getDevice();
717         const vk::DeviceInterface&              vk                      = m_context.getDeviceInterface();
718
719         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
720         {
721                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
722                 DE_NULL,                                                                                        // const void*                          pNext;
723                 cmdPool,                                                                                        // VkCommandPool                        commandPool;
724                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
725                 1u,                                                                                                     // deUint32                                     bufferCount;
726         };
727         vk::Move<vk::VkCommandBuffer>   cmdBuffer       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
728         CmdBufferBeginInfo                              beginInfo       (0u);
729
730         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
731
732         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, 0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
733         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
734
735         std::vector<vk::VkClearValue>   renderPassClearValues(2);
736         deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
737
738         const vk::VkRect2D renderArea =
739         {
740                 { 0,                                    0 },
741                 { StateObjects::WIDTH,  StateObjects::HEIGHT }
742         };
743
744         RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
745
746         vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
747
748         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
749
750         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,     *m_stateObjects->m_pipeline);
751
752         vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
753         const vk::VkDeviceSize vertexBufferOffset = 0;
754         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
755
756         // Draw un-occluded geometry
757         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL, m_testVector.queryControlFlags);
758         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
759         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL);
760
761         // Partially occlude geometry
762         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL, 1, START_VERTEX_PARTIALLY_OCCLUDED, 0);
763
764         // Draw partially-occluded geometry
765         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED, m_testVector.queryControlFlags);
766         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
767         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED);
768
769         // Occlude geometry
770         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_OCCLUDER_DRAWCALL, 1, START_VERTEX_OCCLUDER, 0);
771
772         // Draw occluded geometry
773         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED, m_testVector.queryControlFlags);
774         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
775         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED);
776
777         vk.cmdEndRenderPass(*cmdBuffer);
778
779         if (m_testVector.queryWait != WAIT_QUEUE )
780         {
781                 //For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
782                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
783                 {
784                         vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
785                 }
786         }
787
788         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
789
790         vk.endCommandBuffer(*cmdBuffer);
791
792         return cmdBuffer;
793 }
794
795 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
796 {
797         const vk::VkDevice                              device          = m_context.getDevice();
798         const vk::DeviceInterface&              vk                      = m_context.getDeviceInterface();
799
800         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
801         {
802                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
803                 DE_NULL,                                                                                        // const void*                          pNext;
804                 cmdPool,                                                                                        // VkCommandPool                        commandPool;
805                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
806                 1u,                                                                                                     // deUint32                                     bufferCount;
807         };
808         vk::Move<vk::VkCommandBuffer>   cmdBuffer       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
809         const CmdBufferBeginInfo                beginInfo       (0u);
810
811         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
812         vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
813         vk.endCommandBuffer(*cmdBuffer);
814
815         return cmdBuffer;
816 }
817
818 void OcclusionQueryTestInstance::captureResults (deUint64* retResults, deUint64* retAvailAbility, bool allowNotReady)
819 {
820
821         const vk::VkDevice                      device                  = m_context.getDevice();
822         const vk::DeviceInterface&      vk                              = m_context.getDeviceInterface();
823         std::vector<deUint8>            resultsBuffer   (static_cast<size_t>(m_testVector.queryResultsStride) * NUM_QUERIES_IN_POOL);
824
825         if (m_testVector.queryResultsMode == RESULTS_MODE_GET)
826         {
827                 const vk::VkResult queryResult = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, resultsBuffer.size(), &resultsBuffer[0], m_testVector.queryResultsStride, m_queryResultFlags);
828                 if (queryResult == vk::VK_NOT_READY && !allowNotReady)
829                 {
830                         TCU_FAIL("getQueryPoolResults returned VK_NOT_READY, but results should be already available.");
831                 }
832                 else
833                 {
834                         VK_CHECK(queryResult);
835                 }
836         }
837         else if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
838         {
839                 const vk::Allocation& allocation = m_queryPoolResultsBuffer->getBoundMemory();
840                 const void* allocationData = allocation.getHostPtr();
841
842                 vk::invalidateMappedMemoryRange(vk, device, allocation.getMemory(), allocation.getOffset(), resultsBuffer.size());
843
844                 deMemcpy(&resultsBuffer[0], allocationData, resultsBuffer.size());
845         }
846
847         for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; queryNdx++)
848         {
849                 const void* srcPtr = &resultsBuffer[queryNdx * static_cast<size_t>(m_testVector.queryResultsStride)];
850                 if (m_testVector.queryResultSize == RESULT_SIZE_32_BIT)
851                 {
852                         const deUint32* srcPtrTyped = static_cast<const deUint32*>(srcPtr);
853                         retResults[queryNdx]            = *srcPtrTyped;
854                         if (m_testVector.queryResultsAvailability)
855                         {
856                                 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
857                         }
858                 }
859                 else if (m_testVector.queryResultSize == RESULT_SIZE_64_BIT)
860                 {
861                         const deUint64* srcPtrTyped = static_cast<const deUint64*>(srcPtr);
862                         retResults[queryNdx]            = *srcPtrTyped;
863
864                         if (m_testVector.queryResultsAvailability)
865                         {
866                                 if (m_testVector.queryResultsAvailability)
867                                 {
868                                         retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
869                                 }
870                         }
871                 }
872                 else
873                 {
874                         TCU_FAIL("Wrong m_testVector.queryResultSize");
875                 }
876         }
877 }
878
879 void OcclusionQueryTestInstance::logResults (const deUint64* results, const deUint64* availability)
880 {
881         tcu::TestLog& log = m_context.getTestContext().getLog();
882
883         for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
884         {
885                 if (!m_testVector.queryResultsAvailability)
886                 {
887                         log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << tcu::TestLog::EndMessage;
888                 }
889                 else
890                 {
891                         log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << ", availability   == " << availability[ndx] << tcu::TestLog::EndMessage;
892                 }
893         }
894 }
895
896 bool OcclusionQueryTestInstance::validateResults (const deUint64* results , const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology)
897 {
898         bool passed                     = true;
899         tcu::TestLog& log       = m_context.getTestContext().getLog();
900
901         for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
902         {
903                 deUint64 expectedValueMin = 0;
904                 deUint64 expectedValueMax = 0;
905
906                 if (m_testVector.queryResultsAvailability && availability[queryNdx] == 0)
907                 {
908                         // query result was not available
909                         if (!allowUnavailable)
910                         {
911                                 log << tcu::TestLog::Message << "query results availability was 0 for index "
912                                         << queryNdx << ", expected any value greater than 0." << tcu::TestLog::EndMessage;
913                                 passed = false;
914                                 continue;
915                         }
916                 }
917                 else
918                 {
919                         // query is available, so expect proper result values
920                         if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
921                         {
922                                 switch (queryNdx)
923                                 {
924                                         case QUERY_INDEX_CAPTURE_OCCLUDED:
925                                                 expectedValueMin = 0;
926                                                 expectedValueMax = 0;
927                                                 break;
928                                         case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
929                                                 expectedValueMin = 1;
930                                                 expectedValueMax = 1;
931                                                 break;
932                                         case QUERY_INDEX_CAPTURE_ALL:
933                                                 expectedValueMin = NUM_VERTICES_IN_DRAWCALL;
934                                                 expectedValueMax = NUM_VERTICES_IN_DRAWCALL;
935                                                 break;
936                                 }
937                         }
938                         else if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
939                         {
940                                 switch (queryNdx)
941                                 {
942                                         case QUERY_INDEX_CAPTURE_OCCLUDED:
943                                                 expectedValueMin = 0;
944                                                 expectedValueMax = 0;
945                                                 break;
946                                         case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
947                                         case QUERY_INDEX_CAPTURE_ALL:
948                                                 {
949                                                         const int primWidth             = StateObjects::WIDTH  / 2;
950                                                         const int primHeight    = StateObjects::HEIGHT / 2;
951                                                         const int primArea              = primWidth * primHeight / 2;
952                                                         expectedValueMin                = (int)(0.97f * primArea);
953                                                         expectedValueMax                = (int)(1.03f * primArea);
954                                                 }
955                                 }
956                         }
957                         else
958                         {
959                                 TCU_FAIL("Unsupported primitive topology");
960                         }
961                 }
962
963                 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || (expectedValueMin == 0 && expectedValueMax == 0))
964                 {
965                         // require precise value
966                         if (results[queryNdx] < expectedValueMin || results[queryNdx] > expectedValueMax)
967                         {
968                                 log << tcu::TestLog::Message << "wrong value of query for index "
969                                         << queryNdx << ", expected the value minimum of " << expectedValueMin << ", maximum of " << expectedValueMax << " got "
970                                         << results[queryNdx] << "." << tcu::TestLog::EndMessage;
971                                 passed = false;
972                         }
973                 }
974                 else
975                 {
976                         // require imprecise value greater than 0
977                         if (results[queryNdx] == 0)
978                         {
979                                 log << tcu::TestLog::Message << "wrong value of query for index "
980                                         << queryNdx << ", expected any non-zero value, got "
981                                         << results[queryNdx] << "." << tcu::TestLog::EndMessage;
982                                 passed = false;
983                         }
984                 }
985         }
986         return passed;
987 }
988
989 void OcclusionQueryTestInstance::logRenderTarget (void)
990 {
991         tcu::TestLog&                   log                                             = m_context.getTestContext().getLog();
992         const vk::VkQueue               queue                                   = m_context.getUniversalQueue();
993         const vk::VkOffset3D    zeroOffset                              = { 0, 0, 0 };
994         tcu::ConstPixelBufferAccess resultImageAccess   = m_stateObjects->m_colorAttachmentImage->readSurface(
995                 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
996                 zeroOffset, StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
997
998         log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
999 }
1000
1001 template<class Instance>
1002 class QueryPoolOcclusionTest : public vkt::TestCase
1003 {
1004 public:
1005         QueryPoolOcclusionTest (tcu::TestContext &context, const char *name, const char *description, const OcclusionQueryTestVector& testVector)
1006                 : TestCase                      (context, name, description)
1007                 , m_testVector          (testVector)
1008         {
1009         }
1010 private:
1011         vkt::TestInstance* createInstance (vkt::Context& context) const
1012         {
1013                 return new Instance(context, m_testVector);
1014         }
1015
1016         void initPrograms(vk::SourceCollections& programCollection) const
1017         {
1018                 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 400\n"
1019                                                                                                                                            "layout(location = 0) out vec4 out_FragColor;\n"
1020                                                                                                                                            "void main()\n"
1021                                                                                                                                            "{\n"
1022                                                                                                                                            "    out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
1023                                                                                                                                            "}\n");
1024
1025                 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
1026                                                                                                                                                  "layout(location = 0) in vec4 in_Postion;\n"
1027                                                                                                                                                  "void main() {\n"
1028                                                                                                                                                  "      gl_Position  = in_Postion;\n"
1029                                                                                                                                                  "      gl_PointSize = 1.0;\n"
1030                                                                                                                                                  "}\n");
1031         }
1032
1033         OcclusionQueryTestVector m_testVector;
1034 };
1035
1036 } //anonymous
1037
1038 namespace vkt
1039 {
1040
1041 namespace QueryPool
1042 {
1043
1044 QueryPoolOcclusionTests::QueryPoolOcclusionTests (tcu::TestContext &testCtx)
1045         : TestCaseGroup(testCtx, "occlusion_query", "Tests for occlusion queries")
1046 {
1047         /* Left blank on purpose */
1048 }
1049
1050 QueryPoolOcclusionTests::~QueryPoolOcclusionTests (void)
1051 {
1052         /* Left blank on purpose */
1053 }
1054
1055 void QueryPoolOcclusionTests::init (void)
1056 {
1057         OcclusionQueryTestVector baseTestVector;
1058         baseTestVector.queryControlFlags                = 0;
1059         baseTestVector.queryResultSize                  = RESULT_SIZE_64_BIT;
1060         baseTestVector.queryWait                                = WAIT_QUEUE;
1061         baseTestVector.queryResultsMode                 = RESULTS_MODE_GET;
1062         baseTestVector.queryResultsStride               = sizeof(deUint64);
1063         baseTestVector.queryResultsAvailability = false;
1064         baseTestVector.primitiveTopology                = vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1065
1066         //Basic tests
1067         {
1068                 OcclusionQueryTestVector testVector = baseTestVector;
1069                 testVector.queryControlFlags = 0;
1070                 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_conservative",   "draw with conservative occlusion query",       testVector));
1071                 testVector.queryControlFlags = vk::VK_QUERY_CONTROL_PRECISE_BIT;
1072                 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_precise",                "draw with precise occlusion query",            testVector));
1073         }
1074
1075         // Functional test
1076         {
1077                 vk::VkQueryControlFlags controlFlags[]          = { 0,                                  vk::VK_QUERY_CONTROL_PRECISE_BIT        };
1078                 const char*                             controlFlagsStr[]       = { "conservative",             "precise"                                                       };
1079
1080                 for (int controlFlagIdx = 0; controlFlagIdx < DE_LENGTH_OF_ARRAY(controlFlags); ++controlFlagIdx)
1081                 {
1082
1083                         vk::VkPrimitiveTopology primitiveTopology[]             = { vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST };
1084                         const char*                             primitiveTopologyStr[]  = { "points", "triangles" };
1085                         for (int primitiveTopologyIdx = 0; primitiveTopologyIdx < DE_LENGTH_OF_ARRAY(primitiveTopology); ++primitiveTopologyIdx)
1086                         {
1087
1088                                 OcclusionQueryResultSize        resultSize[]    = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1089                                 const char*                                     resultSizeStr[] = { "32",                               "64" };
1090
1091                                 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSize); ++resultSizeIdx)
1092                                 {
1093
1094                                         OcclusionQueryWait      wait[]          = { WAIT_QUEUE, WAIT_QUERY };
1095                                         const char*                     waitStr[]       = { "queue",    "query" };
1096
1097                                         for (int waitIdx = 0; waitIdx < DE_LENGTH_OF_ARRAY(wait); ++waitIdx)
1098                                         {
1099                                                 OcclusionQueryResultsMode       resultsMode[]           = { RESULTS_MODE_GET,   RESULTS_MODE_COPY };
1100                                                 const char*                                     resultsModeStr[]        = { "get",                              "copy" };
1101
1102                                                 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1103                                                 {
1104
1105                                                         bool testAvailability[]                         = { false, true };
1106                                                         const char* testAvailabilityStr[]       = { "without", "with"};
1107
1108                                                         for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1109                                                         {
1110                                                                 OcclusionQueryTestVector testVector                     = baseTestVector;
1111                                                                 testVector.queryControlFlags                            = controlFlags[controlFlagIdx];
1112                                                                 testVector.queryResultSize                                      = resultSize[resultSizeIdx];
1113                                                                 testVector.queryWait                                            = wait[waitIdx];
1114                                                                 testVector.queryResultsMode                                     = resultsMode[resultsModeIdx];
1115                                                                 testVector.queryResultsStride                           = (testVector.queryResultSize == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1116                                                                 testVector.queryResultsAvailability                     = testAvailability[testAvailabilityIdx];
1117                                                                 testVector.primitiveTopology                            = primitiveTopology[primitiveTopologyIdx];
1118
1119                                                                 if (testVector.queryResultsAvailability)
1120                                                                 {
1121                                                                         testVector.queryResultsStride *= 2;
1122                                                                 }
1123
1124                                                                 std::ostringstream testName;
1125                                                                 std::ostringstream testDescr;
1126
1127                                                                 testName << resultsModeStr[resultsModeIdx] << "_results"
1128                                                                                  << "_" << controlFlagsStr[controlFlagIdx]
1129                                                                                  << "_size_" << resultSizeStr[resultSizeIdx]
1130                                                                                  << "_wait_" << waitStr[waitIdx]
1131                                                                                  << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability"
1132                                                                                  << "_draw_" <<  primitiveTopologyStr[primitiveTopologyIdx];
1133
1134                                                                 testDescr << "draw occluded " << primitiveTopologyStr[primitiveTopologyIdx]
1135                                                                                   << "with " << controlFlagsStr[controlFlagIdx] << ", "
1136                                                                               << resultsModeStr[resultsModeIdx] << " results "
1137                                                                               << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1138                                                                                   << resultSizeStr[resultSizeIdx] << "bit variables,"
1139                                                                               << "wait for results on" << waitStr[waitIdx];
1140
1141                                                                 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1142                                                         }
1143                                                 }
1144                                         }
1145                                 }
1146                         }
1147                 }
1148         }
1149         // Test different strides
1150         {
1151                 OcclusionQueryResultsMode       resultsMode[]           = { RESULTS_MODE_GET,   RESULTS_MODE_COPY       };
1152                 const char*                                     resultsModeStr[]        = { "get",                              "copy"                          };
1153
1154                 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1155                 {
1156                         OcclusionQueryResultSize        resultSizes[]   = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1157                         const char*                                     resultSizeStr[] = { "32", "64" };
1158
1159                         bool testAvailability[]                         = { false,              true    };
1160                         const char* testAvailabilityStr[]       = { "without",  "with"  };
1161
1162                         for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1163                         {
1164                                 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSizes); ++resultSizeIdx)
1165                                 {
1166                                         const vk::VkDeviceSize resultSize       = (resultSizes[resultSizeIdx] == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1167
1168                                         // \todo [2015-12-18 scygan] Ensure only stride values aligned to resultSize are allowed. Otherwise test should be extended.
1169                                         const vk::VkDeviceSize strides[]        =
1170                                         {
1171                                                 1 * resultSize,
1172                                                 2 * resultSize,
1173                                                 3 * resultSize,
1174                                                 4 * resultSize,
1175                                                 5 * resultSize,
1176                                                 13 * resultSize,
1177                                                 1024 * resultSize
1178                                         };
1179
1180                                         for (int strideIdx = 0; strideIdx < DE_LENGTH_OF_ARRAY(strides); strideIdx++)
1181                                         {
1182                                                 OcclusionQueryTestVector testVector             = baseTestVector;
1183                                                 testVector.queryResultsMode                             = resultsMode[resultsModeIdx];
1184                                                 testVector.queryResultSize                              = resultSizes[resultSizeIdx];
1185                                                 testVector.queryResultsAvailability             = testAvailability[testAvailabilityIdx];
1186                                                 testVector.queryResultsStride                   = strides[strideIdx];
1187
1188                                                 const vk::VkDeviceSize elementSize              = (testVector.queryResultsAvailability ? resultSize * 2 : resultSize);
1189
1190                                                 if (elementSize > testVector.queryResultsStride)
1191                                                 {
1192                                                         continue;
1193                                                 }
1194
1195                                                 std::ostringstream testName;
1196                                                 std::ostringstream testDescr;
1197
1198                                                 testName << resultsModeStr[resultsModeIdx]
1199                                                                  << "_results_size_" << resultSizeStr[resultSizeIdx]
1200                                                                  << "_stride_" << strides[strideIdx]
1201                                                                  << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability";
1202
1203                                                 testDescr << resultsModeStr[resultsModeIdx] << " results "
1204                                                                   << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1205                                                                   << resultSizeStr[resultSizeIdx] << "bit variables, with stride" << strides[strideIdx];
1206
1207                                                 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1208                                         }
1209                                 }
1210                         }
1211                 }
1212
1213         }
1214 }
1215
1216 } //QueryPool
1217 } //vkt
1218