1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
6 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Vulkan Fill Buffer Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktApiFillBufferTests.hpp"
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"
53 enum { TEST_DATA_SIZE = 256 };
56 VkDeviceSize dstOffset;
58 deUint32 testData[TEST_DATA_SIZE];
61 class FillBufferTestInstance : public vkt::TestInstance
64 FillBufferTestInstance (Context& context,
65 TestParams testParams);
66 virtual tcu::TestStatus iterate (void);
68 const TestParams m_params;
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;
76 VkCommandBufferBeginInfo m_cmdBufferBeginInfo;
78 Move<VkBuffer> m_destination;
79 de::MovePtr<Allocation> m_destinationBufferAlloc;
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
87 return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat());
91 FillBufferTestInstance::FillBufferTestInstance (Context& context, TestParams testParams)
92 : vkt::TestInstance (context)
93 , m_params (testParams)
95 const DeviceInterface& vk = context.getDeviceInterface();
96 const VkDevice vkDevice = context.getDevice();
97 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
98 Allocator& memAlloc = context.getDefaultAllocator();
100 // Create command pool
101 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
103 // Create command buffer
104 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
107 m_fence = createFence(vk, vkDevice);
109 // Create desctination buffer
111 const VkBufferCreateInfo destinationBufferParams =
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;
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()));
129 tcu::TestStatus FillBufferTestInstance::iterate (void)
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));
134 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
136 generateExpectedResult();
138 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
140 const DeviceInterface& vk = m_context.getDeviceInterface();
141 const VkDevice vkDevice = m_context.getDevice();
142 const VkQueue queue = m_context.getUniversalQueue();
144 const VkBufferMemoryBarrier dstBufferBarrier =
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;
157 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
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,
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));
170 const VkSubmitInfo submitInfo =
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;
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 */));
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()));
192 return checkTestResult(resultLevel->getAccess());
195 void FillBufferTestInstance::generateBuffer (tcu::PixelBufferAccess buffer, int width, int height, int depth)
197 for (int z = 0; z < depth; z++)
199 for (int y = 0; y < height; y++)
201 for (int x = 0; x < width; x++)
202 buffer.setPixel(tcu::UVec4(x, y, z, 255), x, y, z);
207 void FillBufferTestInstance::uploadBuffer (tcu::ConstPixelBufferAccess bufferAccess, const Allocation& bufferAlloc)
209 const DeviceInterface& vk = m_context.getDeviceInterface();
210 const VkDevice vkDevice = m_context.getDevice();
211 const deUint32 bufferSize = calculateSize(bufferAccess);
214 deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize);
215 flushMappedMemoryRange(vk, vkDevice, bufferAlloc.getMemory(), bufferAlloc.getOffset(), bufferSize);
218 tcu::TestStatus FillBufferTestInstance::checkTestResult (tcu::ConstPixelBufferAccess result)
220 const tcu::ConstPixelBufferAccess expected = m_expectedTextureLevel->getAccess();
221 const tcu::UVec4 threshold (0, 0, 0, 0);
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");
226 return tcu::TestStatus::pass("Fill and Update Buffer test");
229 void FillBufferTestInstance::generateExpectedResult (void)
231 const tcu::ConstPixelBufferAccess dst = m_destinationTextureLevel->getAccess();
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);
236 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
237 deUint32* endPtr = currentPtr + m_params.size / 4;
239 while (currentPtr < endPtr)
241 *currentPtr = m_params.testData[0];
246 class FillBufferTestCase : public vkt::TestCase
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)
257 virtual TestInstance* createInstance (Context& context) const
259 return (TestInstance*) new FillBufferTestInstance(context, m_params);
262 const TestParams m_params;
267 class UpdateBufferTestInstance : public FillBufferTestInstance
270 UpdateBufferTestInstance (Context& context,
271 TestParams testParams)
272 : FillBufferTestInstance(context, testParams)
274 virtual tcu::TestStatus iterate (void);
277 virtual void generateExpectedResult (void);
280 tcu::TestStatus UpdateBufferTestInstance::iterate (void)
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));
285 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
287 generateExpectedResult();
289 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
291 const DeviceInterface& vk = m_context.getDeviceInterface();
292 const VkDevice vkDevice = m_context.getDevice();
293 const VkQueue queue = m_context.getUniversalQueue();
295 const VkBufferMemoryBarrier dstBufferBarrier =
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;
308 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
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,
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));
321 const VkSubmitInfo submitInfo =
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;
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 */));
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()));
343 return checkTestResult(resultLevel->getAccess());
346 void UpdateBufferTestInstance::generateExpectedResult (void)
348 const tcu::ConstPixelBufferAccess dst = m_destinationTextureLevel->getAccess();
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);
353 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
355 deMemcpy(currentPtr, m_params.testData, (size_t)m_params.size);
358 class UpdateBufferTestCase : public vkt::TestCase
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)
369 virtual TestInstance* createInstance (Context& context) const
371 return (TestInstance*) new UpdateBufferTestInstance(context, m_params);
379 tcu::TestCaseGroup* createFillAndUpdateBufferTests (tcu::TestContext& testCtx)
381 de::MovePtr<tcu::TestCaseGroup> fillAndUpdateBufferTests (new tcu::TestCaseGroup(testCtx, "fill_and_update_buffer", "Fill and Update Buffer Tests"));
383 params.dstSize = TestParams::TEST_DATA_SIZE;
385 DE_ASSERT(params.dstSize <= TestParams::TEST_DATA_SIZE);
386 deMemset(params.testData, 0xFFu, (size_t)params.dstSize);
389 const std::string description ("whole buffer");
390 const std::string testName ("buffer_whole");
392 params.dstOffset = 0;
393 params.size = params.dstSize;
395 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
396 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
400 const std::string description ("first word in buffer");
401 const std::string testName ("buffer_first_one");
403 params.dstOffset = 0;
406 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
407 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
411 const std::string description ("second word in buffer");
412 const std::string testName ("buffer_second_one");
414 params.dstOffset = 4;
417 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
418 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
422 const std::string description ("buffer second part");
423 const std::string testName ("buffer_second_part");
425 params.dstOffset = params.dstSize / 2;
426 params.size = params.dstSize / 2;
428 fillAndUpdateBufferTests->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
429 fillAndUpdateBufferTests->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
432 return fillAndUpdateBufferTests.release();