1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 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 Protected memory copy image to buffer tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktProtectedMemCopyImageToBufferTests.hpp"
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktProtectedMemBufferValidator.hpp"
45 namespace ProtectedMem
56 MAX_POSITION = BUFFER_SIZE / 4,
60 class CopyImageToBufferTestInstance : public ProtectedTestInstance
63 CopyImageToBufferTestInstance (Context& ctx,
64 const vk::VkClearColorValue fillValue,
65 const BufferValidator<T>& validator,
66 const CmdBufferType cmdBufferType);
67 virtual tcu::TestStatus iterate (void);
70 const vk::VkFormat m_imageFormat;
71 const vk::VkClearColorValue m_fillValue;
72 const BufferValidator<T>& m_validator;
73 const CmdBufferType m_cmdBufferType;
78 class CopyImageToBufferTestCase : public TestCase
81 CopyImageToBufferTestCase (tcu::TestContext& testCtx,
82 const std::string& name,
83 vk::VkClearColorValue fillValue,
84 ValidationData<T> data,
85 CmdBufferType cmdBufferType)
86 : TestCase (testCtx, name, "Copy image to buffer.")
87 , m_fillValue (fillValue)
89 , m_cmdBufferType (cmdBufferType)
93 virtual ~CopyImageToBufferTestCase (void) {}
94 virtual TestInstance* createInstance (Context& ctx) const
96 return new CopyImageToBufferTestInstance<T>(ctx, m_fillValue, m_validator, m_cmdBufferType);
98 virtual void initPrograms (vk::SourceCollections& programCollection) const
100 m_validator.initPrograms(programCollection);
103 vk::VkClearColorValue m_fillValue;
104 BufferValidator<T> m_validator;
105 CmdBufferType m_cmdBufferType;
109 CopyImageToBufferTestInstance<T>::CopyImageToBufferTestInstance (Context& ctx,
110 const vk::VkClearColorValue fillValue,
111 const BufferValidator<T>& validator,
112 const CmdBufferType cmdBufferType)
113 : ProtectedTestInstance (ctx)
114 , m_imageFormat (vk::VK_FORMAT_R32G32B32A32_UINT)
115 , m_fillValue (fillValue)
116 , m_validator (validator)
117 , m_cmdBufferType (cmdBufferType)
122 tcu::TestStatus CopyImageToBufferTestInstance<T>::iterate()
124 ProtectedContext& ctx (m_protectedContext);
125 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
126 const vk::VkDevice device = ctx.getDevice();
127 const vk::VkQueue queue = ctx.getQueue();
128 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
131 de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
132 RENDER_WIDTH, RENDER_HEIGHT,
134 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT
135 | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT
136 | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
137 de::MovePtr<vk::BufferWithMemory> dstBuffer (makeBuffer(ctx,
140 (deUint32)(BUFFER_SIZE * sizeof(deUint32)),
141 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
142 | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
143 vk::MemoryRequirement::Protected));
145 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
146 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
147 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
148 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
151 beginCommandBuffer(vk, *cmdBuffer);
153 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
155 // Begin secondary command buffer
156 const vk::VkCommandBufferInheritanceInfo secCmdBufInheritInfo =
158 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
160 (vk::VkRenderPass)0u, // renderPass
162 (vk::VkFramebuffer)0u, // framebuffer
163 VK_FALSE, // occlusionQueryEnable
164 (vk::VkQueryControlFlags)0u, // queryFlags
165 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
167 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, secCmdBufInheritInfo);
170 // Start image barrier for source image.
172 const vk::VkImageMemoryBarrier startImgBarrier =
174 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
175 DE_NULL, // const void* pNext
176 0, // VkAccessFlags srcAccessMask
177 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
178 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
179 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout
180 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
181 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
182 **colorImage, // VkImage image
184 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
185 0u, // uint32_t baseMipLevel
186 1u, // uint32_t mipLevels
187 0u, // uint32_t baseArraySlice
188 1u, // uint32_t subresourceRange
192 vk.cmdPipelineBarrier(targetCmdBuffer,
193 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
194 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
195 (vk::VkDependencyFlags)0,
196 0, (const vk::VkMemoryBarrier*)DE_NULL,
197 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
198 1, &startImgBarrier);
202 const vk::VkImageSubresourceRange subresourceRange =
204 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
205 0u, // uint32_t baseMipLevel
206 1u, // uint32_t levelCount
207 0u, // uint32_t baseArrayLayer
208 1u, // uint32_t layerCount
211 vk.cmdClearColorImage(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_GENERAL, &m_fillValue, 1, &subresourceRange);
213 // Image barrier to change accessMask to transfer read bit for source image.
215 const vk::VkImageMemoryBarrier initializeBarrier =
217 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
218 DE_NULL, // const void* pNext
219 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
220 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
221 vk::VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout oldLayout
222 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout
223 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
224 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
225 **colorImage, // VkImage image
227 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
228 0u, // uint32_t baseMipLevel
229 1u, // uint32_t mipLevels
230 0u, // uint32_t baseArraySlice
231 1u, // uint32_t subresourceRange
235 vk.cmdPipelineBarrier(targetCmdBuffer,
236 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
237 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
238 (vk::VkDependencyFlags)0,
239 0, (const vk::VkMemoryBarrier*)DE_NULL,
240 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
241 1, &initializeBarrier);
244 // Copy image to buffer
245 const vk::VkImageSubresourceLayers subresourceLayers =
247 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
248 0u, // uint32_t mipLevel
249 0u, // uint32_t baseArrayLayer
250 1u, // uint32_t layerCount
252 const vk::VkOffset3D nullOffset = {0u, 0u, 0u};
253 const vk::VkExtent3D imageExtent = {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
254 const vk::VkBufferImageCopy copyRegion =
256 0ull, // VkDeviceSize srcOffset;
257 0, // uint32_t bufferRowLength
258 0, // uint32_t bufferImageHeight
259 subresourceLayers, // VkImageSubresourceLayers imageSubresource
260 nullOffset, // VkOffset3D imageOffset
261 imageExtent, // VkExtent3D imageExtent
263 vk.cmdCopyImageToBuffer(targetCmdBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **dstBuffer, 1u, ©Region);
266 // Buffer validator reads buffer in compute shader
267 const vk::VkBufferMemoryBarrier endBufferBarrier =
269 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
270 DE_NULL, // const void* pNext
271 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
272 vk::VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask
273 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
274 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
275 **dstBuffer, // VkBuffer buffer
276 0u, // VkDeviceSize offset
277 VK_WHOLE_SIZE, // VkDeviceSize size
279 vk.cmdPipelineBarrier(targetCmdBuffer,
280 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
281 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
282 (vk::VkDependencyFlags)0,
283 0, (const vk::VkMemoryBarrier*)DE_NULL,
284 1, &endBufferBarrier,
285 0, (const vk::VkImageMemoryBarrier*)DE_NULL);
288 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
290 endCommandBuffer(vk, *secondaryCmdBuffer);
291 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
294 endCommandBuffer(vk, *cmdBuffer);
296 // Submit command buffer
297 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
298 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
301 ctx.getTestContext().getLog()
302 << tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
304 // Validate resulting buffer
305 if (m_validator.validateBuffer(ctx, **dstBuffer))
306 return tcu::TestStatus::pass("Everything went OK");
308 return tcu::TestStatus::fail("Something went really wrong");
311 tcu::TestCaseGroup* createCopyImageToFloatBufferTests(tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
314 const vk::VkClearColorValue fillValue;
315 const ValidationDataVec4 data;
317 { { { 0.0f, 0.0f, 0.0f, 0.0f } },
319 { tcu::IVec4(0), tcu::IVec4(1), tcu::IVec4(3), tcu::IVec4(7) },
320 { tcu::Vec4(0.0f), tcu::Vec4(0.0f), tcu::Vec4(0.0f), tcu::Vec4(0.0f) }
323 { { { 1.0f, 1.0f, 1.0f, 1.0f } },
325 { tcu::IVec4(2), tcu::IVec4(4), tcu::IVec4(16), tcu::IVec4(15) },
326 { tcu::Vec4(1.0f), tcu::Vec4(1.0f), tcu::Vec4(1.0f), tcu::Vec4(1.0f) }
329 { { { 0.24f, 0.24f, 0.24f, 0.24f } },
331 { tcu::IVec4(3), tcu::IVec4(7), tcu::IVec4(17), tcu::IVec4(37) },
332 { tcu::Vec4(0.24f), tcu::Vec4(0.24f), tcu::Vec4(0.24f), tcu::Vec4(0.24f) }
335 { { { 0.68f, 0.68f, 0.68f, 0.68f } },
337 { tcu::IVec4(7), tcu::IVec4(11), tcu::IVec4(21), tcu::IVec4(40) },
338 { tcu::Vec4(0.68f), tcu::Vec4(0.68f), tcu::Vec4(0.68f), tcu::Vec4(0.68f) }
341 { { { 0.92f, 0.92f, 0.92f, 0.92f } },
343 { tcu::IVec4(5), tcu::IVec4(21), tcu::IVec4(40), tcu::IVec4(57) },
344 { tcu::Vec4(0.92f), tcu::Vec4(0.92f), tcu::Vec4(0.92f), tcu::Vec4(0.92f) }
347 { { { 0.49f, 0.49f, 0.49f, 0.49f } },
349 { tcu::IVec4(23), tcu::IVec4(37), tcu::IVec4(51), tcu::IVec4(63) },
350 { tcu::Vec4(0.49f), tcu::Vec4(0.49f), tcu::Vec4(0.49f), tcu::Vec4(0.49f) }
355 de::MovePtr<tcu::TestCaseGroup> copyStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Copy Image to Buffer Tests with static input"));
357 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
359 DE_ASSERT(testData[ndx].data.positions[0].x() < MAX_POSITION);
360 DE_ASSERT(testData[ndx].data.positions[1].x() < MAX_POSITION);
361 DE_ASSERT(testData[ndx].data.positions[2].x() < MAX_POSITION);
362 DE_ASSERT(testData[ndx].data.positions[3].x() < MAX_POSITION);
364 const std::string name = "copy_" + de::toString(ndx + 1);
365 copyStaticTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), testData[ndx].fillValue, testData[ndx].data, cmdBufferType));
368 /* Add a few randomized tests */
369 de::MovePtr<tcu::TestCaseGroup> copyRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Copy Image to Buffer Tests with random input"));
370 const int testCount = 10;
371 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
372 for (int ndx = 0; ndx < testCount; ++ndx)
374 const std::string name = "copy_" + de::toString(ndx + 1);
375 vk::VkClearValue clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
376 const tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
377 const tcu::IVec4 vec0 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
378 const tcu::IVec4 vec1 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
379 const tcu::IVec4 vec2 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
380 const tcu::IVec4 vec3 = tcu::IVec4(rnd.getInt(0, MAX_POSITION - 1));
382 ValidationDataVec4 data =
384 { vec0, vec1, vec2, vec3 },
385 { refValue, refValue, refValue, refValue }
388 DE_ASSERT(data.positions[0].x() < MAX_POSITION);
389 DE_ASSERT(data.positions[1].x() < MAX_POSITION);
390 DE_ASSERT(data.positions[2].x() < MAX_POSITION);
391 DE_ASSERT(data.positions[3].x() < MAX_POSITION);
393 copyRandomTests->addChild(new CopyImageToBufferTestCase<tcu::Vec4>(testCtx, name.c_str(), clearValue.color, data, cmdBufferType));
396 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
397 std::string groupDesc = "Copy Image to Buffer Tests with " + groupName + " command buffer";
398 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
399 copyTests->addChild(copyStaticTests.release());
400 copyTests->addChild(copyRandomTests.release());
401 return copyTests.release();
406 tcu::TestCaseGroup* createCopyImageToFloatBufferTests (tcu::TestContext& testCtx)
408 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, "copy_image_to_float_buffer", "Copy Image to Buffer Tests"));
410 copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_PRIMARY));
411 copyTests->addChild(createCopyImageToFloatBufferTests(testCtx, CMD_BUFFER_SECONDARY));
413 return copyTests.release();