dEQP-VK.renderpass: Set IMAGE_USAGE_TRANSFER_SRC_BIT when needed
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / query_pool / vktQueryPoolOcclusionTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and/or associated documentation files (the
10  * "Materials"), to deal in the Materials without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sublicense, and/or sell copies of the Materials, and to
13  * permit persons to whom the Materials are furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice(s) and this permission notice shall be included
17  * in all copies or substantial portions of the Materials.
18  *
19  * The Materials are Confidential Information as defined by the
20  * Khronos Membership Agreement until designated non-confidential by Khronos,
21  * at which point this condition clause shall be removed.
22  *
23  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
30  *
31  *//*!
32  * \file
33  * \brief Vulkan Occlusion Query Tests
34  *//*--------------------------------------------------------------------*/
35
36 #include "vktQueryPoolOcclusionTests.hpp"
37
38 #include "vktTestCase.hpp"
39
40 #include "vktQueryPoolImageObjectUtil.hpp"
41 #include "vktQueryPoolBufferObjectUtil.hpp"
42 #include "vktQueryPoolCreateInfoUtil.hpp"
43 #include "vkBuilderUtil.hpp"
44 #include "vkRefUtil.hpp"
45 #include "vkPrograms.hpp"
46
47 #include "tcuTestLog.hpp"
48 #include "tcuResource.hpp"
49 #include "tcuImageCompare.hpp"
50 #include "tcuCommandLine.hpp"
51
52 using namespace vkt::QueryPool;
53
54 namespace
55 {
56
57 struct StateObjects
58 {
59                         StateObjects    (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive);
60         void    setVertices             (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices);
61
62         enum
63         {
64                 WIDTH   = 128,
65                 HEIGHT  = 128
66         };
67
68         vkt::Context &m_context;
69
70         vk::Move<vk::VkPipeline>                m_pipeline;
71         vk::Move<vk::VkPipelineLayout>  m_pipelineLayout;
72
73         de::SharedPtr<Image>                    m_colorAttachmentImage, m_DepthImage;
74         vk::Move<vk::VkImageView>               m_attachmentView;
75         vk::Move<vk::VkImageView>               m_depthiew;
76
77         vk::Move<vk::VkRenderPass>              m_renderPass;
78         vk::Move<vk::VkFramebuffer>             m_framebuffer;
79
80         de::SharedPtr<Buffer>                   m_vertexBuffer;
81
82         vk::VkFormat                                    m_colorAttachmentFormat;
83 };
84
85 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
86         : m_context(context)
87         , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
88
89 {
90         vk::VkFormat            depthFormat = vk::VK_FORMAT_D16_UNORM;
91         const vk::VkDevice      device          = m_context.getDevice();
92
93         //attachment images and views
94         {
95                 vk::VkExtent3D imageExtent =
96                 {
97                         WIDTH,  // width;
98                         HEIGHT, // height;
99                         1               // depth;
100                 };
101
102                 const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
103                                                                                                    vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
104
105                 m_colorAttachmentImage  = Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator());
106
107                 const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
108                 m_attachmentView                = vk::createImageView(vk, device, &attachmentViewInfo);
109
110                 ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
111                         vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
112
113                 m_DepthImage                    = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator());
114
115                 // Construct a depth  view from depth image
116                 const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
117                 m_depthiew                              = vk::createImageView(vk, device, &depthViewInfo);
118         }
119
120         {
121                 // Renderpass and Framebuffer
122
123                 RenderPassCreateInfo renderPassCreateInfo;
124                 renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,                                                                       // format
125                                                                                                                                         vk::VK_SAMPLE_COUNT_1_BIT,                                                              // samples
126                                                                                                                                         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                                // loadOp
127                                                                                                                                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // storeOp
128                                                                                                                                         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                    // stencilLoadOp
129                                                                                                                                         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                   // stencilLoadOp
130                                                                                                                                         vk::VK_IMAGE_LAYOUT_GENERAL,                                                    // initialLauout
131                                                                                                                                         vk::VK_IMAGE_LAYOUT_GENERAL));                                                  // finalLayout
132
133                 renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat,                                                                                           // format
134                                                                                                                                  vk::VK_SAMPLE_COUNT_1_BIT,                                                                     // samples
135                                                                                                                                  vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                                                       // loadOp
136                                                                                                                                  vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                          // storeOp
137                                                                                                                                  vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                           // stencilLoadOp
138                                                                                                                                  vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,                                          // stencilLoadOp
139                                                                                                                                  vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,          // initialLauout
140                                                                                                                                  vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));        // finalLayout
141
142                 const vk::VkAttachmentReference colorAttachmentReference =
143                 {
144                         0,                                                                                                                      // attachment
145                         vk::VK_IMAGE_LAYOUT_GENERAL                                                                     // layout
146                 };
147
148                 const vk::VkAttachmentReference depthAttachmentReference =
149                 {
150                         1,                                                                                                                      // attachment
151                         vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL            // layout
152                 };
153
154                 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                                 // pipelineBindPoint
155                                                                                                                    0,                                                                                                   // flags
156                                                                                                                    0,                                                                                                   // inputCount
157                                                                                                                    DE_NULL,                                                                                             // pInputAttachments
158                                                                                                                    1,                                                                                                   // colorCount
159                                                                                                                    &colorAttachmentReference,                                                   // pColorAttachments
160                                                                                                                    DE_NULL,                                                                                             // pResolveAttachments
161                                                                                                                    depthAttachmentReference,                                                    // depthStencilAttachment
162                                                                                                                    0,                                                                                                   // preserveCount
163                                                                                                                    DE_NULL));                                                                                   // preserveAttachments
164
165                 m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
166
167                 std::vector<vk::VkImageView> attachments(2);
168                 attachments[0] = *m_attachmentView;
169                 attachments[1] = *m_depthiew;
170
171                 FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
172                 m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
173         }
174
175         {
176                 // Pipeline
177
178                 vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
179                 vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
180
181                 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
182
183                 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
184                 m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
185
186                 const vk::VkVertexInputBindingDescription vf_binding_desc               =
187                 {
188                         0,                                                                                                                              // binding;
189                         4 * (deUint32)sizeof(float),                                                                    // stride;
190                         vk::VK_VERTEX_INPUT_RATE_VERTEX                                                                 // inputRate
191                 };
192
193                 const vk::VkVertexInputAttributeDescription vf_attribute_desc   =
194                 {
195                         0,                                                                                                                              // location;
196                         0,                                                                                                                              // binding;
197                         vk::VK_FORMAT_R32G32B32A32_SFLOAT,                                                              // format;
198                         0                                                                                                                               // offset;
199                 };
200
201                 const vk::VkPipelineVertexInputStateCreateInfo vf_info                  =
202                 {                                                                                                                                       // sType;
203                         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,  // pNext;
204                         NULL,                                                                                                                   // flags;
205                         0u,                                                                                                                             // vertexBindingDescriptionCount;
206                         1,                                                                                                                              // pVertexBindingDescriptions;
207                         &vf_binding_desc,                                                                                               // vertexAttributeDescriptionCount;
208                         1,                                                                                                                              // pVertexAttributeDescriptions;
209                         &vf_attribute_desc
210                 };
211
212                 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
213                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
214                 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
215                 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
216                 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
217                 const vk::VkViewport viewport   =
218                 {
219                         0,              // float x;
220                         0,              // float y;
221                         WIDTH,  // float width;
222                         HEIGHT, // float height;
223                         0.0f,   // float minDepth;
224                         1.0f    // float maxDepth;
225                 };
226
227                 const vk::VkRect2D scissor              =
228                 {
229                         {
230                                 0,              // deInt32 x
231                                 0,              // deInt32 y
232                         },              // VkOffset2D   offset;
233                         {
234                                 WIDTH,  // deInt32 width;
235                                 HEIGHT, // deInt32 height
236                         },              // VkExtent2D   extent;
237                 };
238                 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
239                 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
240                 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
241                 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
242                 pipelineCreateInfo.addState(vf_info);
243                 m_pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
244         }
245
246         {
247                 // Vertex buffer
248                 const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
249                 m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
250         }
251 }
252
253 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
254 {
255         const vk::VkDevice device                       = m_context.getDevice();
256
257         tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_vertexBuffer->getBoundMemory().getHostPtr());
258         std::copy(vertices.begin(), vertices.end(), ptr);
259
260         vk::flushMappedMemoryRange(vk, device,  m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(),     vertices.size() * sizeof(vertices[0]));
261 }
262
263 enum OcclusionQueryResultSize
264 {
265         RESULT_SIZE_64_BIT,
266         RESULT_SIZE_32_BIT,
267 };
268
269 enum OcclusionQueryWait
270 {
271         WAIT_QUEUE,
272         WAIT_QUERY,
273         WAIT_NONE
274 };
275
276 enum OcclusionQueryResultsMode
277 {
278         RESULTS_MODE_GET,
279         RESULTS_MODE_COPY
280 };
281
282 struct OcclusionQueryTestVector
283 {
284         vk::VkQueryControlFlags         queryControlFlags;
285         OcclusionQueryResultSize        queryResultSize;
286         OcclusionQueryWait                      queryWait;
287         OcclusionQueryResultsMode       queryResultsMode;
288         vk::VkDeviceSize                        queryResultsStride;
289         bool                                            queryResultsAvailability;
290         vk::VkPrimitiveTopology         primitiveRopology;
291 };
292
293 class BasicOcclusionQueryTestInstance : public vkt::TestInstance
294 {
295 public:
296                                         BasicOcclusionQueryTestInstance         (vkt::Context &context, const OcclusionQueryTestVector&  testVector);
297                                         ~BasicOcclusionQueryTestInstance        (void);
298 private:
299         tcu::TestStatus iterate                                                         (void);
300
301         enum
302         {
303                 NUM_QUERIES_IN_POOL                             = 2,
304                 QUERY_INDEX_CAPTURE_EMPTY               = 0,
305                 QUERY_INDEX_CAPTURE_DRAWCALL    = 1,
306                 NUM_VERTICES_IN_DRAWCALL                = 3
307         };
308
309         OcclusionQueryTestVector        m_testVector;
310         StateObjects*                           m_stateObjects;
311         vk::VkQueryPool                         m_queryPool;
312 };
313
314 BasicOcclusionQueryTestInstance::BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector&  testVector)
315         : TestInstance          (context)
316         , m_testVector          (testVector)
317         , m_stateObjects        (new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, m_testVector.primitiveRopology))
318 {
319         DE_ASSERT(testVector.queryResultSize                    == RESULT_SIZE_64_BIT
320                         && testVector.queryWait                                 == WAIT_QUEUE
321                         && testVector.queryResultsMode                  == RESULTS_MODE_GET
322                         && testVector.queryResultsStride                == sizeof(deUint64)
323                         && testVector.queryResultsAvailability  == false
324                         && testVector.primitiveRopology                 == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
325
326         const vk::VkDevice                      device  = m_context.getDevice();
327         const vk::DeviceInterface&      vk              = m_context.getDeviceInterface();
328
329         const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
330         {
331                 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
332                 DE_NULL,
333                 0u,
334                 vk::VK_QUERY_TYPE_OCCLUSION,
335                 NUM_QUERIES_IN_POOL,
336                 0
337         };
338         VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
339
340         std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
341         vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
342         vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
343         vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
344         m_stateObjects->setVertices(vk, vertices);
345 }
346
347 BasicOcclusionQueryTestInstance::~BasicOcclusionQueryTestInstance (void)
348 {
349         if (m_stateObjects)
350                 delete m_stateObjects;
351
352         if (m_queryPool != DE_NULL)
353         {
354                 const vk::VkDevice device               = m_context.getDevice();
355                 const vk::DeviceInterface& vk   = m_context.getDeviceInterface();
356
357                 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
358         }
359 }
360
361 tcu::TestStatus BasicOcclusionQueryTestInstance::iterate (void)
362 {
363         tcu::TestLog &log                               = m_context.getTestContext().getLog();
364         const vk::VkDevice device               = m_context.getDevice();
365         const vk::VkQueue queue                 = m_context.getUniversalQueue();
366         const vk::DeviceInterface& vk   = m_context.getDeviceInterface();
367
368         const CmdPoolCreateInfo                 cmdPoolCreateInfo       (m_context.getUniversalQueueFamilyIndex());
369         vk::Move<vk::VkCommandPool>             cmdPool                         = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
370
371         const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
372         {
373                 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,     // VkStructureType                      sType;
374                 DE_NULL,                                                                                        // const void*                          pNext;
375                 *cmdPool,                                                                                       // VkCommandPool                        commandPool;
376                 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,                            // VkCommandBufferLevel         level;
377                 1u,                                                                                                     // deUint32                                     bufferCount;
378         };
379         vk::Unique<vk::VkCommandBuffer> cmdBuffer                       (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
380         const CmdBufferBeginInfo                beginInfo                       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
381
382         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
383
384         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
385         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
386
387         std::vector<vk::VkClearValue> renderPassClearValues(2);
388         deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
389
390         const vk::VkRect2D renderArea =
391         {
392                 { 0,                                    0 },
393                 { StateObjects::WIDTH,  StateObjects::HEIGHT }
394         };
395
396         RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
397
398         vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
399
400         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
401
402         vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
403
404         vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
405         const vk::VkDeviceSize vertexBufferOffset = 0;
406         vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
407
408         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY, m_testVector.queryControlFlags);
409         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY);
410
411         vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL, m_testVector.queryControlFlags);
412         vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
413         vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL);
414
415         vk.cmdEndRenderPass(*cmdBuffer);
416
417         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
418
419         vk.endCommandBuffer(*cmdBuffer);
420
421         // Submit command buffer
422         const vk::VkSubmitInfo submitInfo =
423         {
424                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
425                 DE_NULL,                                                        // const void*                          pNext;
426                 0,                                                                      // deUint32                                     waitSemaphoreCount;
427                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
428                 1,                                                                      // deUint32                                     commandBufferCount;
429                 &cmdBuffer.get(),                                       // const VkCommandBuffer*       pCommandBuffers;
430                 0,                                                                      // deUint32                                     signalSemaphoreCount;
431                 DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
432         };
433         vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
434
435         VK_CHECK(vk.queueWaitIdle(queue));
436
437         deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
438         size_t queryResultsSize         = sizeof(queryResults);
439
440         vk::VkResult queryResult        = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
441
442         if (queryResult == vk::VK_NOT_READY)
443         {
444                 TCU_FAIL("Query result not avaliable, but vkWaitIdle() was called.");
445         }
446
447         VK_CHECK(queryResult);
448
449         log << tcu::TestLog::Section("OcclusionQueryResults",
450                 "Occlusion query results");
451         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
452         {
453                 log << tcu::TestLog::Message << "query[ slot == " << ndx
454                         << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
455         }
456
457         bool passed = true;
458
459         for (int queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
460         {
461
462                 deUint64 expectedValue;
463
464                 switch (queryNdx)
465                 {
466                         case QUERY_INDEX_CAPTURE_EMPTY:
467                                 expectedValue = 0;
468                                 break;
469                         case QUERY_INDEX_CAPTURE_DRAWCALL:
470                                 expectedValue = NUM_VERTICES_IN_DRAWCALL;
471                                 break;
472                 }
473
474                 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || expectedValue == 0)
475                 {
476                         // require precise value
477                         if (queryResults[queryNdx] != expectedValue)
478                         {
479                                 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
480                                         "wrong value of query for index "
481                                         << queryNdx << ", expected " << expectedValue << ", got "
482                                         << queryResults[0] << "." << tcu::TestLog::EndMessage;
483                                 passed = false;
484                         }
485                 }
486                 else
487                 {
488                         // require imprecize value > 0
489                         if (queryResults[queryNdx] == 0)
490                         {
491                                 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
492                                         "wrong value of query for index "
493                                         << queryNdx << ", expected any non-zero value, got "
494                                         << queryResults[0] << "." << tcu::TestLog::EndMessage;
495                                 passed = false;
496                         }
497                 }
498         }
499         log << tcu::TestLog::EndSection;
500
501         const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
502
503         tcu::ConstPixelBufferAccess resultImageAccess = m_stateObjects->m_colorAttachmentImage->readSurface(
504                                 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
505                                 zeroOffset,  StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
506
507         log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
508
509         if (passed)
510         {
511                 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
512         }
513         return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
514 }
515
516 class OcclusionQueryTestInstance : public vkt::TestInstance
517 {
518 public:
519         OcclusionQueryTestInstance              (vkt::Context &context, const OcclusionQueryTestVector& testVector);
520         ~OcclusionQueryTestInstance             (void);
521 private:
522         tcu::TestStatus                                 iterate                                                 (void);
523
524         vk::Move<vk::VkCommandBuffer>   recordRender                                    (vk::VkCommandPool commandPool);
525         vk::Move<vk::VkCommandBuffer>   recordCopyResults                               (vk::VkCommandPool commandPool);
526
527         void                                                    captureResults                                  (deUint64*                      retResults,     deUint64*               retAvailability,        bool    allowNotReady);
528         void                                                    logResults                                              (const deUint64*        results,        const deUint64* availability);
529         bool                                                    validateResults                                 (const deUint64*        results,        const deUint64* availability,           bool    allowUnavailable,       vk::VkPrimitiveTopology primitiveTopology);
530         void                                                    logRenderTarget                                 (void);
531
532         enum
533         {
534                 NUM_QUERIES_IN_POOL                                                     = 3,
535                 QUERY_INDEX_CAPTURE_ALL                                         = 0,
536                 QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED          = 1,
537                 QUERY_INDEX_CAPTURE_OCCLUDED                            = 2
538         };
539         enum
540         {
541                 NUM_VERTICES_IN_DRAWCALL                                        = 3,
542                 NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL     = 3,
543                 NUM_VERTICES_IN_OCCLUDER_DRAWCALL                       = 3,
544                 NUM_VERTICES                                                            = NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL
545         };
546         enum
547         {
548                 START_VERTEX                                                            = 0,
549                 START_VERTEX_PARTIALLY_OCCLUDED                         = START_VERTEX + NUM_VERTICES_IN_DRAWCALL,
550                 START_VERTEX_OCCLUDER                                           = START_VERTEX_PARTIALLY_OCCLUDED + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL
551         };
552
553         OcclusionQueryTestVector                m_testVector;
554
555         const vk::VkQueryResultFlags    m_queryResultFlags;
556
557         StateObjects*                                   m_stateObjects;
558         vk::VkQueryPool                                 m_queryPool;
559         de::SharedPtr<Buffer>                   m_queryPoolResultsBuffer;
560
561         vk::Move<vk::VkCommandPool>             m_commandPool;
562         vk::Move<vk::VkCommandBuffer>   m_renderCommandBuffer;
563         vk::Move<vk::VkCommandBuffer>   m_copyResultsCommandBuffer;
564 };
565
566 OcclusionQueryTestInstance::OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
567         : vkt::TestInstance             (context)
568         , m_testVector                  (testVector)
569         , m_queryResultFlags    ((m_testVector.queryWait == WAIT_QUERY                                  ? vk::VK_QUERY_RESULT_WAIT_BIT                          : 0)
570                                                         | (m_testVector.queryResultSize == RESULT_SIZE_64_BIT   ? vk::VK_QUERY_RESULT_64_BIT                            : 0)
571                                                         | (m_testVector.queryResultsAvailability                                ? vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT     : 0))
572         , m_stateObjects                (new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL, m_testVector.primitiveRopology))
573 {
574         const vk::VkDevice                      device                          = m_context.getDevice();
575         const vk::DeviceInterface&      vk                                      = m_context.getDeviceInterface();
576
577         const vk::VkQueryPoolCreateInfo queryPoolCreateInfo     =
578         {
579                 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
580                 DE_NULL,
581                 0u,
582                 vk::VK_QUERY_TYPE_OCCLUSION,
583                 NUM_QUERIES_IN_POOL,
584                 0
585         };
586
587         VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
588
589         if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
590         {
591                 const vk::VkDeviceSize  resultsBufferSize                       = m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL;
592                                                                 m_queryPoolResultsBuffer        = Buffer::createAndAlloc(vk, device, BufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
593         }
594
595         const CmdPoolCreateInfo cmdPoolCreateInfo               (m_context.getUniversalQueueFamilyIndex());
596                                                         m_commandPool                   = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
597                                                         m_renderCommandBuffer   = recordRender(*m_commandPool);
598
599         if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
600         {
601                 m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
602         }
603 }
604
605 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
606 {
607         const vk::VkDevice device = m_context.getDevice();
608
609         if (m_stateObjects)
610                 delete m_stateObjects;
611
612         if (m_queryPool != DE_NULL)
613         {
614                 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
615                 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
616         }
617 }
618
619 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
620 {
621         const vk::VkQueue                       queue           = m_context.getUniversalQueue();
622         const vk::DeviceInterface&      vk                      = m_context.getDeviceInterface();
623         tcu::TestLog&                           log                     = m_context.getTestContext().getLog();
624         std::vector<tcu::Vec4>          vertices        (NUM_VERTICES);
625
626         // 1st triangle
627         vertices[START_VERTEX + 0] = tcu::Vec4( 0.5,  0.5, 0.5, 1.0);
628         vertices[START_VERTEX + 1] = tcu::Vec4( 0.5, -0.5, 0.5, 1.0);
629         vertices[START_VERTEX + 2] = tcu::Vec4(-0.5,  0.5, 0.5, 1.0);
630         // 2nd triangle - partially occluding the scene
631         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 0] = tcu::Vec4(-0.5, -0.5, 1.0, 1.0);
632         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
633         vertices[START_VERTEX_PARTIALLY_OCCLUDED + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
634         // 3nd triangle - fully occluding the scene
635         vertices[START_VERTEX_OCCLUDER + 0] = tcu::Vec4( 0.5,  0.5, 1.0, 1.0);
636         vertices[START_VERTEX_OCCLUDER + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
637         vertices[START_VERTEX_OCCLUDER + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
638
639         m_stateObjects->setVertices(vk, vertices);
640
641         {
642                 const vk::VkSubmitInfo submitInfo =
643                 {
644                         vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
645                         DE_NULL,                                                        // const void*                          pNext;
646                         0,                                                                      // deUint32                                     waitSemaphoreCount;
647                         DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
648                         1,                                                                      // deUint32                                     commandBufferCount;
649                         &m_renderCommandBuffer.get(),           // const VkCommandBuffer*       pCommandBuffers;
650                         0,                                                                      // deUint32                                     signalSemaphoreCount;
651                         DE_NULL                                                         // const VkSemaphore*           pSignalSemaphores;
652                 };
653                 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
654         }
655
656         if (m_testVector.queryWait == WAIT_QUEUE)
657         {
658                 VK_CHECK(vk.queueWaitIdle(queue));
659
660                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
661                 {
662                         // In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
663                         // contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
664
665                         // In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
666
667                         const vk::VkSubmitInfo submitInfo =
668                         {
669                                 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,      // VkStructureType                      sType;
670                                 DE_NULL,                                                        // const void*                          pNext;
671                                 0,                                                                      // deUint32                                     waitSemaphoreCount;
672                                 DE_NULL,                                                        // const VkSemaphore*           pWaitSemaphores;
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.primitiveRopology);
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       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
729
730         vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
731
732         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
733         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
734
735         std::vector<vk::VkClearValue>   renderPassClearValues(2);
736         deMemset(&renderPassClearValues[0], 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         if (m_testVector.queryWait != WAIT_QUEUE )
778         {
779                 //For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
780                 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
781                 {
782                         vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
783                 }
784         }
785
786         vk.cmdEndRenderPass(*cmdBuffer);
787
788         transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
789
790         vk.endCommandBuffer(*cmdBuffer);
791
792         return cmdBuffer;
793 }
794
795 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
796 {
797         const vk::VkDevice                              device          = m_context.getDevice();
798         const vk::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       (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
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.primitiveRopology                = 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.primitiveRopology                            = 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