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"
26 #include "vktApiBufferAndImageAllocationUtil.hpp"
28 #include "deStringUtil.hpp"
29 #include "deUniquePtr.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "tcuImageCompare.hpp"
37 #include "tcuTexture.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuVectorType.hpp"
40 #include "deSharedPtr.hpp"
61 VkDeviceSize dstOffset;
63 deUint32 testData[TEST_DATA_SIZE];
64 de::SharedPtr<IBufferAllocator> bufferAllocator;
67 class FillBufferTestInstance : public vkt::TestInstance
70 FillBufferTestInstance (Context& context,
71 TestParams testParams);
72 virtual tcu::TestStatus iterate (void);
74 const TestParams m_params;
76 Move<VkCommandPool> m_cmdPool;
77 Move<VkCommandBuffer> m_cmdBuffer;
78 Move<VkFence> m_fence;
79 de::MovePtr<tcu::TextureLevel> m_destinationTextureLevel;
80 de::MovePtr<tcu::TextureLevel> m_expectedTextureLevel;
82 VkCommandBufferBeginInfo m_cmdBufferBeginInfo;
84 Move<VkBuffer> m_destination;
85 de::MovePtr<Allocation> m_destinationBufferAlloc;
87 void generateBuffer (tcu::PixelBufferAccess buffer,
91 virtual void generateExpectedResult (void);
92 void uploadBuffer (tcu::ConstPixelBufferAccess
94 const Allocation& bufferAlloc);
95 virtual tcu::TestStatus checkTestResult (tcu::ConstPixelBufferAccess
97 deUint32 calculateSize (tcu::ConstPixelBufferAccess
100 return src.getWidth() * src.getHeight() * src.getDepth() * tcu::getPixelSize(src.getFormat());
104 FillBufferTestInstance::FillBufferTestInstance
106 TestParams testParams)
107 : vkt::TestInstance (context)
108 , m_params (testParams)
110 const DeviceInterface& vk = context.getDeviceInterface();
111 const VkDevice vkDevice = context.getDevice();
112 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
113 Allocator& memAlloc = context.getDefaultAllocator();
115 // Create command pool
116 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
118 // Create command buffer
119 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
122 m_fence = createFence(vk, vkDevice);
124 testParams.bufferAllocator->createTestBuffer(m_params.dstSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, context, memAlloc, m_destination, MemoryRequirement::HostVisible, m_destinationBufferAlloc);
127 tcu::TestStatus FillBufferTestInstance::iterate (void)
129 const int dstLevelWidth = (int)(m_params.dstSize / 4);
130 m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
132 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
134 generateExpectedResult();
136 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
138 const DeviceInterface& vk = m_context.getDeviceInterface();
139 const VkDevice vkDevice = m_context.getDevice();
140 const VkQueue queue = m_context.getUniversalQueue();
142 const VkBufferMemoryBarrier dstBufferBarrier =
144 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
145 DE_NULL, // const void* pNext;
146 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
147 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
148 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
149 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
150 *m_destination, // VkBuffer buffer;
151 0u, // VkDeviceSize offset;
152 m_params.dstOffset // VkDeviceSize size;
155 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
157 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
158 DE_NULL, // const void* pNext;
159 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
160 (const VkCommandBufferInheritanceInfo*)DE_NULL,
163 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
164 vk.cmdFillBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData[0]);
165 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);
166 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
168 const VkSubmitInfo submitInfo =
170 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
171 DE_NULL, // const void* pNext;
172 0u, // deUint32 waitSemaphoreCount;
173 DE_NULL, // const VkSemaphore* pWaitSemaphores;
174 (const VkPipelineStageFlags*)DE_NULL,
175 1u, // deUint32 commandBufferCount;
176 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
177 0u, // deUint32 signalSemaphoreCount;
178 DE_NULL // const VkSemaphore* pSignalSemaphores;
181 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
182 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
183 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
186 de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
187 invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_params.dstOffset);
188 tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
190 return checkTestResult(resultLevel->getAccess());
193 void FillBufferTestInstance::generateBuffer
194 (tcu::PixelBufferAccess buffer,
199 for (int z = 0; z < depth; z++)
201 for (int y = 0; y < height; y++)
203 for (int x = 0; x < width; x++)
204 buffer.setPixel(tcu::UVec4(x, y, z, 255), x, y, z);
209 void FillBufferTestInstance::uploadBuffer
210 (tcu::ConstPixelBufferAccess
212 const Allocation& bufferAlloc)
214 const DeviceInterface& vk = m_context.getDeviceInterface();
215 const VkDevice vkDevice = m_context.getDevice();
216 const deUint32 bufferSize = calculateSize(bufferAccess);
219 deMemcpy(bufferAlloc.getHostPtr(), bufferAccess.getDataPtr(), bufferSize);
220 flushMappedMemoryRange(vk, vkDevice, bufferAlloc.getMemory(), bufferAlloc.getOffset(), bufferSize);
223 tcu::TestStatus FillBufferTestInstance::checkTestResult
224 (tcu::ConstPixelBufferAccess
227 const tcu::ConstPixelBufferAccess
228 expected = m_expectedTextureLevel->getAccess();
229 const tcu::UVec4 threshold (0, 0, 0, 0);
231 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparsion", expected, result, threshold, tcu::COMPARE_LOG_RESULT))
233 return tcu::TestStatus::fail("Fill and Update Buffer test");
236 return tcu::TestStatus::pass("Fill and Update Buffer test");
239 void FillBufferTestInstance::generateExpectedResult
242 const tcu::ConstPixelBufferAccess
243 dst = m_destinationTextureLevel->getAccess();
245 m_expectedTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
246 tcu::copy(m_expectedTextureLevel->getAccess(), dst);
248 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
249 deUint32* endPtr = currentPtr + m_params.size / 4;
251 while (currentPtr < endPtr)
253 *currentPtr = m_params.testData[0];
258 class FillBufferTestCase : public vkt::TestCase
261 FillBufferTestCase (tcu::TestContext& testCtx,
262 const std::string& name,
263 const std::string& description,
264 const TestParams params)
265 : vkt::TestCase (testCtx, name, description)
269 virtual TestInstance* createInstance (Context& context) const
271 return static_cast<TestInstance*>(new FillBufferTestInstance(context, m_params));
274 const TestParams m_params;
279 class UpdateBufferTestInstance : public FillBufferTestInstance
282 UpdateBufferTestInstance (Context& context,
283 TestParams testParams)
284 : FillBufferTestInstance (context, testParams)
286 virtual tcu::TestStatus iterate (void);
289 virtual void generateExpectedResult (void);
292 tcu::TestStatus UpdateBufferTestInstance::iterate (void)
294 const int dstLevelWidth = (int)(m_params.dstSize / 4);
295 m_destinationTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT), dstLevelWidth, 1));
297 generateBuffer(m_destinationTextureLevel->getAccess(), dstLevelWidth, 1, 1);
299 generateExpectedResult();
301 uploadBuffer(m_destinationTextureLevel->getAccess(), *m_destinationBufferAlloc);
303 const DeviceInterface& vk = m_context.getDeviceInterface();
304 const VkDevice vkDevice = m_context.getDevice();
305 const VkQueue queue = m_context.getUniversalQueue();
307 const VkBufferMemoryBarrier dstBufferBarrier =
309 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
310 DE_NULL, // const void* pNext;
311 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
312 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask;
313 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
314 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
315 *m_destination, // VkBuffer buffer;
316 0u, // VkDeviceSize offset;
317 m_params.dstOffset // VkDeviceSize size;
320 const VkCommandBufferBeginInfo cmdBufferBeginInfo =
322 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
323 DE_NULL, // const void* pNext;
324 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
325 (const VkCommandBufferInheritanceInfo*)DE_NULL,
328 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
329 vk.cmdUpdateBuffer(*m_cmdBuffer, *m_destination, m_params.dstOffset, m_params.size, m_params.testData);
330 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);
331 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
333 const VkSubmitInfo submitInfo =
335 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
336 DE_NULL, // const void* pNext;
337 0u, // deUint32 waitSemaphoreCount;
338 DE_NULL, // const VkSemaphore* pWaitSemaphores;
339 (const VkPipelineStageFlags*)DE_NULL,
340 1u, // deUint32 commandBufferCount;
341 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
342 0u, // deUint32 signalSemaphoreCount;
343 DE_NULL // const VkSemaphore* pSignalSemaphores;
346 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
347 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
348 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */));
351 de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(m_destinationTextureLevel->getAccess().getFormat(), dstLevelWidth, 1));
352 invalidateMappedMemoryRange(vk, vkDevice, m_destinationBufferAlloc->getMemory(), m_destinationBufferAlloc->getOffset(), m_params.dstOffset);
353 tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), m_destinationBufferAlloc->getHostPtr()));
355 return checkTestResult(resultLevel->getAccess());
358 void UpdateBufferTestInstance::generateExpectedResult
361 const tcu::ConstPixelBufferAccess
362 dst = m_destinationTextureLevel->getAccess();
364 m_expectedTextureLevel = de::MovePtr<tcu::TextureLevel>(new tcu::TextureLevel(dst.getFormat(), dst.getWidth(), dst.getHeight(), dst.getDepth()));
365 tcu::copy(m_expectedTextureLevel->getAccess(), dst);
367 deUint32* currentPtr = (deUint32*) m_expectedTextureLevel->getAccess().getDataPtr() + m_params.dstOffset / 4;
369 deMemcpy(currentPtr, m_params.testData, (size_t)m_params.size);
372 class UpdateBufferTestCase : public vkt::TestCase
375 UpdateBufferTestCase (tcu::TestContext& testCtx,
376 const std::string& name,
377 const std::string& description,
378 const TestParams params)
379 : vkt::TestCase (testCtx, name, description)
383 virtual TestInstance* createInstance (Context& context) const
385 return (TestInstance*) new UpdateBufferTestInstance(context, m_params);
393 tcu::TestCaseGroup* createFillAndUpdateBufferTests (tcu::TestContext& testCtx)
395 const de::SharedPtr<IBufferAllocator>
398 de::SharedPtr<BufferSuballocation>(new BufferSuballocation()),
399 de::SharedPtr<BufferDedicatedAllocation>(new BufferDedicatedAllocation())
402 de::MovePtr<tcu::TestCaseGroup> fillAndUpdateBufferTests (new tcu::TestCaseGroup(testCtx, "fill_and_update_buffer", "Fill and Update Buffer Tests"));
403 tcu::TestCaseGroup* bufferViewAllocationGroupTests[]
406 new tcu::TestCaseGroup(testCtx, "suballocation", "BufferView Fill and Update Tests for Suballocated Objects"),
407 new tcu::TestCaseGroup(testCtx, "dedicated_alloc", "BufferView Fill and Update Tests for Dedicatedly Allocated Objects")
409 for (deUint32 subgroupNdx = 0u; subgroupNdx < DE_LENGTH_OF_ARRAY(bufferViewAllocationGroupTests); ++subgroupNdx)
411 if (bufferViewAllocationGroupTests[subgroupNdx] == DE_NULL)
413 TCU_THROW(InternalError, "Could not create test subgroup.");
415 fillAndUpdateBufferTests->addChild(bufferViewAllocationGroupTests[subgroupNdx]);
418 params.dstSize = TestParams::TEST_DATA_SIZE;
421 for (deUint32 buffersAllocationNdx = 0u; buffersAllocationNdx < DE_LENGTH_OF_ARRAY(bufferAllocators); ++buffersAllocationNdx)
423 DE_ASSERT(params.dstSize <= TestParams::TEST_DATA_SIZE);
424 deMemset(params.testData, 0xFFu, (size_t)params.dstSize);
425 params.bufferAllocator = bufferAllocators[buffersAllocationNdx];
426 const deUint32 testCaseGroupNdx = buffersAllocationNdx;
427 tcu::TestCaseGroup* currentTestsGroup = bufferViewAllocationGroupTests[testCaseGroupNdx];
430 const std::string description ("whole buffer");
431 const std::string testName ("buffer_whole");
433 params.dstOffset = 0;
434 params.size = params.dstSize;
436 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
437 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
441 const std::string description ("first word in buffer");
442 const std::string testName ("buffer_first_one");
444 params.dstOffset = 0;
447 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
448 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
452 const std::string description ("second word in buffer");
453 const std::string testName ("buffer_second_one");
455 params.dstOffset = 4;
458 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
459 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
463 const std::string description ("buffer second part");
464 const std::string testName ("buffer_second_part");
466 params.dstOffset = params.dstSize / 2;
467 params.size = params.dstSize / 2;
469 currentTestsGroup->addChild(new FillBufferTestCase(testCtx, "fill_" + testName, "Fill " + description, params));
470 currentTestsGroup->addChild(new UpdateBufferTestCase(testCtx, "update_" + testName, "Update " + description, params));
474 return fillAndUpdateBufferTests.release();