67352697e20ee3a3fab02df2f2b1d46b5d3c76a4
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / api / vktApiFillBufferTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 Fill Buffer Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktApiFillBufferTests.hpp"
26
27 #include "deStringUtil.hpp"
28 #include "deUniquePtr.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vktTestCase.hpp"
32 #include "vktTestCaseUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTexture.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuVectorType.hpp"
39
40 namespace vkt
41 {
42
43 namespace api
44 {
45
46 using namespace vk;
47
48 namespace
49 {
50
51 struct TestParams
52 {
53         enum { TEST_DATA_SIZE = 256 };
54
55         VkDeviceSize    dstSize;
56         VkDeviceSize    dstOffset;
57         VkDeviceSize    size;
58         deUint32                testData[TEST_DATA_SIZE];
59 };
60
61 class FillBufferTestInstance : public vkt::TestInstance
62 {
63 public:
64                                                                                 FillBufferTestInstance          (Context&       context,
65                                                                                                                                          TestParams     testParams);
66         virtual tcu::TestStatus                         iterate                                         (void);
67 protected:
68         const TestParams                                        m_params;
69
70         Move<VkCommandPool>                                     m_cmdPool;
71         Move<VkCommandBuffer>                           m_cmdBuffer;
72         Move<VkFence>                                           m_fence;
73         de::MovePtr<tcu::TextureLevel>          m_destinationTextureLevel;
74         de::MovePtr<tcu::TextureLevel>          m_expectedTextureLevel;
75
76         VkCommandBufferBeginInfo                        m_cmdBufferBeginInfo;
77
78         Move<VkBuffer>                                          m_destination;
79         de::MovePtr<Allocation>                         m_destinationBufferAlloc;
80
81         void                                                            generateBuffer                          (tcu::PixelBufferAccess buffer, int width, int height, int depth = 1);
82         virtual void                                            generateExpectedResult          (void);
83         void                                                            uploadBuffer                            (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc);
84         virtual tcu::TestStatus                         checkTestResult                         (tcu::ConstPixelBufferAccess result);
85         deUint32                                                        calculateSize                           (tcu::ConstPixelBufferAccess src) const
86                                                                                 {
87                                                                                         return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat());
88                                                                                 }
89 };
90
91 FillBufferTestInstance::FillBufferTestInstance (Context& context, TestParams testParams)
92         : vkt::TestInstance     (context)
93         , m_params                      (testParams)
94 {
95         const DeviceInterface&          vk                                      = context.getDeviceInterface();
96         const VkDevice                          vkDevice                        = context.getDevice();
97         const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
98         Allocator&                                      memAlloc                        = context.getDefaultAllocator();
99
100         // Create command pool
101         m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
102
103         // Create command buffer
104         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
105
106         // Create fence
107         m_fence = createFence(vk, vkDevice);
108
109         // Create desctination buffer
110         {
111                 const VkBufferCreateInfo                        destinationBufferParams =
112                 {
113                         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType              sType;
114                         DE_NULL,                                                                        // const void*                  pNext;
115                         0u,                                                                                     // VkBufferCreateFlags  flags;
116                         m_params.dstSize,                                                       // VkDeviceSize                 size;
117                         VK_BUFFER_USAGE_TRANSFER_DST_BIT,                       // VkBufferUsageFlags   usage;
118                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode                sharingMode;
119                         1u,                                                                                     // deUint32                             queueFamilyIndexCount;
120                         &queueFamilyIndex,                                                      // const deUint32*              pQueueFamilyIndices;
121                 };
122
123                 m_destination                           = createBuffer(vk, vkDevice, &destinationBufferParams);
124                 m_destinationBufferAlloc        = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_destination), MemoryRequirement::HostVisible);
125                 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_destination, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset()));
126         }
127 }
128
129 tcu::TestStatus FillBufferTestInstance::iterate (void)
130 {
131         const int       dstLevelWidth           = (int)(m_params.dstSize / 4);
132         m_destinationTextureLevel               = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
133
134         generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
135
136         generateExpectedResult();
137
138         uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
139
140         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
141         const VkDevice                          vkDevice        = m_context.getDevice();
142         const VkQueue                           queue           = m_context.getUniversalQueue();
143
144         const VkBufferMemoryBarrier             dstBufferBarrier        =
145         {
146                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
147                 DE_NULL,                                                                        // const void*          pNext;
148                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags        srcAccessMask;
149                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags        dstAccessMask;
150                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
151                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex;
152                 *m_destination,                                                         // VkBuffer                     buffer;
153                 0u,                                                                                     // VkDeviceSize         offset;
154                 m_params.dstOffset                                                      // VkDeviceSize         size;
155         };
156
157         const VkCommandBufferBeginInfo  cmdBufferBeginInfo      =
158         {
159                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                    // VkStructureType                                      sType;
160                 DE_NULL,                                                                                                // const void*                                          pNext;
161                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,                    // VkCommandBufferUsageFlags            flags;
162                 (const VkCommandBufferInheritanceInfo*)DE_NULL,
163         };
164
165         VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
166         vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData[0]);
167         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
168         VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
169
170         const VkSubmitInfo                              submitInfo                      =
171         {
172                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
173                 DE_NULL,                                                // const void*                          pNext;
174                 0u,                                                             // deUint32                                     waitSemaphoreCount;
175                 DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
176                 (const VkPipelineStageFlags*)DE_NULL,
177                 1u,                                                             // deUint32                                     commandBufferCount;
178                 &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
179                 0u,                                                             // deUint32                                     signalSemaphoreCount;
180                 DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
181         };
182
183         VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
184         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
185         VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
186
187         // Read buffer data
188         de::MovePtr<tcu::TextureLevel>  resultLevel     (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
189         invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_params.dstOffset);
190         tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
191
192         return checkTestResult(resultLevel->getAccess());
193 }
194
195 void FillBufferTestInstance::generateBuffer (tcu::PixelBufferAccess buffer, int width, int height, int depth)
196 {
197         for (int z = 0; z < depth; z++)
198         {
199                 for (int y = 0; y < height; y++)
200                 {
201                         for (int x = 0; x < width; x++)
202                                 buffer.setPixel(tcu::UVec4(x, y, z, 255), x, y, z);
203                 }
204         }
205 }
206
207 void FillBufferTestInstance::uploadBuffer (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc)
208 {
209         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
210         const VkDevice                          vkDevice        = m_context.getDevice();
211         const deUint32                          bufferSize      = calculateSize(bufferAccess);
212
213         // Write buffer data
214         deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize);
215         flushMappedMemoryRange(vk, vkDevice, bufferAlloc.getMemory(), bufferAlloc.getOffset(), bufferSize);
216 }
217
218 tcu::TestStatus FillBufferTestInstance::checkTestResult (tcu::ConstPixelBufferAccess result)
219 {
220         const tcu::ConstPixelBufferAccess       expected        = m_expectedTextureLevel->getAccess();
221         const tcu::UVec4                                        threshold       (0, 0, 0, 0);
222
223         if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expected, result, threshold, tcu::COMPARE_LOG_RESULT))
224                 return tcu::TestStatus::fail("Fill and Update Buffer test");
225
226         return tcu::TestStatus::pass("Fill and Update Buffer test");
227 }
228
229 void FillBufferTestInstance::generateExpectedResult (void)
230 {
231         const tcu::ConstPixelBufferAccess       dst     = m_destinationTextureLevel->getAccess();
232
233         m_expectedTextureLevel  = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
234         tcu::copy(m_expectedTextureLevel->getAccess(), dst);
235
236         deUint32*       currentPtr      = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
237         deUint32*       endPtr          = currentPtr + m_params.size / 4;
238
239         while (currentPtr < endPtr)
240         {
241                 *currentPtr = m_params.testData[0];
242                 currentPtr++;
243         }
244 }
245
246 class FillBufferTestCase : public vkt::TestCase
247 {
248 public:
249                                                         FillBufferTestCase      (tcu::TestContext&      testCtx,
250                                                                                                  const std::string&     name,
251                                                                                                  const std::string&     description,
252                                                                                                  const TestParams       params)
253                                                                 : vkt::TestCase (testCtx, name, description)
254                                                                 , m_params              (params)
255                                                         {}
256
257         virtual TestInstance*   createInstance          (Context&                       context) const
258                                                         {
259                                                                 return (TestInstance*) new FillBufferTestInstance(context, m_params);
260                                                         }
261 private:
262         const TestParams                m_params;
263 };
264
265 // Update Buffer
266
267 class UpdateBufferTestInstance : public FillBufferTestInstance
268 {
269 public:
270                                                                                 UpdateBufferTestInstance                (Context&       context,
271                                                                                                                                                  TestParams     testParams)
272                                                                                         : FillBufferTestInstance(context, testParams)
273                                                                                 {}
274         virtual tcu::TestStatus                         iterate                                                 (void);
275
276 protected:
277         virtual void                                            generateExpectedResult                  (void);
278 };
279
280 tcu::TestStatus UpdateBufferTestInstance::iterate (void)
281 {
282         const int       dstLevelWidth           = (int)(m_params.dstSize / 4);
283         m_destinationTextureLevel               = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
284
285         generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
286
287         generateExpectedResult();
288
289         uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
290
291         const DeviceInterface&          vk                      = m_context.getDeviceInterface();
292         const VkDevice                          vkDevice        = m_context.getDevice();
293         const VkQueue                           queue           = m_context.getUniversalQueue();
294
295         const VkBufferMemoryBarrier             dstBufferBarrier        =
296         {
297                 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        // VkStructureType      sType;
298                 DE_NULL,                                                                        // const void*          pNext;
299                 VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags        srcAccessMask;
300                 VK_ACCESS_HOST_READ_BIT,                                        // VkAccessFlags        dstAccessMask;
301                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     srcQueueFamilyIndex;
302                 VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                     dstQueueFamilyIndex;
303                 *m_destination,                                                         // VkBuffer                     buffer;
304                 0u,                                                                                     // VkDeviceSize         offset;
305                 m_params.dstOffset                                                      // VkDeviceSize         size;
306         };
307
308         const VkCommandBufferBeginInfo  cmdBufferBeginInfo      =
309         {
310                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                    // VkStructureType                                      sType;
311                 DE_NULL,                                                                                                // const void*                                          pNext;
312                 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,                    // VkCommandBufferUsageFlags            flags;
313                 (const VkCommandBufferInheritanceInfo*)DE_NULL,
314         };
315
316         VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
317         vk.cmdUpdateBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData);
318         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &dstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
319         VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
320
321         const VkSubmitInfo                              submitInfo                      =
322         {
323                 VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
324                 DE_NULL,                                                // const void*                          pNext;
325                 0u,                                                             // deUint32                                     waitSemaphoreCount;
326                 DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
327                 (const VkPipelineStageFlags*)DE_NULL,
328                 1u,                                                             // deUint32                                     commandBufferCount;
329                 &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
330                 0u,                                                             // deUint32                                     signalSemaphoreCount;
331                 DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
332         };
333
334         VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
335         VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
336         VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
337
338         // Read buffer data
339         de::MovePtr<tcu::TextureLevel>  resultLevel     (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
340         invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_params.dstOffset);
341         tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
342
343         return checkTestResult(resultLevel->getAccess());
344 }
345
346 void UpdateBufferTestInstance::generateExpectedResult (void)
347 {
348         const tcu::ConstPixelBufferAccess       dst     = m_destinationTextureLevel->getAccess();
349
350         m_expectedTextureLevel  = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
351         tcu::copy(m_expectedTextureLevel->getAccess(), dst);
352
353         deUint32*       currentPtr      = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
354
355         deMemcpy(currentPtr, m_params.testData, (size_t)m_params.size);
356 }
357
358 class UpdateBufferTestCase : public vkt::TestCase
359 {
360 public:
361                                                         UpdateBufferTestCase    (tcu::TestContext&      testCtx,
362                                                                                                          const std::string&     name,
363                                                                                                          const std::string&     description,
364                                                                                                          const TestParams       params)
365                                                                 : vkt::TestCase (testCtx, name, description)
366                                                                 , m_params              (params)
367                                                         {}
368
369         virtual TestInstance*   createInstance                  (Context&                       context) const
370                                                         {
371                                                                 return (TestInstance*) new UpdateBufferTestInstance(context, m_params);
372                                                         }
373 private:
374         TestParams                              m_params;
375 };
376
377 } // anonymous
378
379 tcu::TestCaseGroup* createFillAndUpdateBufferTests (tcu::TestContext& testCtx)
380 {
381         de::MovePtr<tcu::TestCaseGroup> fillAndUpdateBufferTests        (new tcu::TestCaseGroup(testCtx, "fill_and_update_buffer", "Fill and Update Buffer Tests"));
382         TestParams                                              params;
383         params.dstSize = TestParams::TEST_DATA_SIZE;
384
385         DE_ASSERT(params.dstSize <= TestParams::TEST_DATA_SIZE);
386         deMemset(params.testData, 0xFFu, (size_t)params.dstSize);
387
388         {
389                 const std::string       description     ("whole buffer");
390                 const std::string       testName        ("buffer_whole");
391
392                 params.dstOffset        = 0;
393                 params.size                     = params.dstSize;
394
395                 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
396                 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
397         }
398
399         {
400                 const std::string       description     ("first word in buffer");
401                 const std::string       testName        ("buffer_first_one");
402
403                 params.dstOffset        = 0;
404                 params.size                     = 4;
405
406                 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
407                 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
408         }
409
410         {
411                 const std::string       description     ("second word in buffer");
412                 const std::string       testName        ("buffer_second_one");
413
414                 params.dstOffset        = 4;
415                 params.size                     = 4;
416
417                 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
418                 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
419         }
420
421         {
422                 const std::string       description     ("buffer second part");
423                 const std::string       testName        ("buffer_second_part");
424
425                 params.dstOffset        = params.dstSize / 2;
426                 params.size                     = params.dstSize / 2;
427
428                 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
429                 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
430         }
431
432         return fillAndUpdateBufferTests.release();
433 }
434
435 } // api
436 } // vkt