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 content copy buffer to image tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktProtectedMemCopyBufferToImageTests.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 "vktProtectedMemImageValidator.hpp"
45 namespace ProtectedMem
57 class CopyBufferToImageTestInstance : public ProtectedTestInstance
60 CopyBufferToImageTestInstance (Context& ctx,
61 const deUint32 fillValue,
62 const ValidationData& refData,
63 const ImageValidator& validator,
64 const CmdBufferType cmdBufferType);
65 virtual tcu::TestStatus iterate (void);
68 const vk::VkFormat m_imageFormat;
69 const deUint32 m_fillValue;
70 const ValidationData& m_refData;
71 const ImageValidator& m_validator;
72 const CmdBufferType m_cmdBufferType;
75 class CopyBufferToImageTestCase : public TestCase
78 CopyBufferToImageTestCase (tcu::TestContext& testCtx,
79 const std::string& name,
82 CmdBufferType cmdBufferType)
83 : TestCase (testCtx, name, "Copy buffer to image.")
84 , m_fillValue (fillValue)
86 , m_validator (vk::VK_FORMAT_R32G32B32A32_SFLOAT)
87 , m_cmdBufferType (cmdBufferType)
91 virtual ~CopyBufferToImageTestCase (void) {}
92 virtual TestInstance* createInstance (Context& ctx) const
94 return new CopyBufferToImageTestInstance(ctx, m_fillValue, m_refData, m_validator, m_cmdBufferType);
96 virtual void initPrograms (vk::SourceCollections& programCollection) const
98 m_validator.initPrograms(programCollection);
101 deUint32 m_fillValue;
102 ValidationData m_refData;
103 ImageValidator m_validator;
104 CmdBufferType m_cmdBufferType;
107 CopyBufferToImageTestInstance::CopyBufferToImageTestInstance (Context& ctx,
108 const deUint32 fillValue,
109 const ValidationData& refData,
110 const ImageValidator& validator,
111 const CmdBufferType cmdBufferType)
112 : ProtectedTestInstance (ctx)
113 , m_imageFormat (vk::VK_FORMAT_R32G32B32A32_SFLOAT)
114 , m_fillValue (fillValue)
115 , m_refData (refData)
116 , m_validator (validator)
117 , m_cmdBufferType (cmdBufferType)
121 tcu::TestStatus CopyBufferToImageTestInstance::iterate()
123 ProtectedContext& ctx (m_protectedContext);
124 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
125 const vk::VkDevice device = ctx.getDevice();
126 const vk::VkQueue queue = ctx.getQueue();
127 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
129 // Create destination image
130 de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
131 RENDER_WIDTH, RENDER_HEIGHT,
133 vk::VK_IMAGE_USAGE_SAMPLED_BIT|vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
134 de::MovePtr<vk::BufferWithMemory> srcBuffer (makeBuffer(ctx,
137 (deUint32)(BUFFER_SIZE * sizeof(deUint32)),
138 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
139 | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT
140 | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
141 vk::MemoryRequirement::Protected));
143 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
144 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
145 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
146 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
149 beginCommandBuffer(vk, *cmdBuffer);
151 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
153 // Begin secondary command buffer
154 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo =
156 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType
158 DE_NULL, // renderPass
160 DE_NULL, // framebuffer
161 VK_FALSE, // occlusionQueryEnable
162 (vk::VkQueryControlFlags)0u, // queryFlags
163 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
165 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
168 // Start src buffer barrier
170 const vk::VkBufferMemoryBarrier startBufferBarrier =
172 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
173 DE_NULL, // const void* pNext
174 0, // VkAccessFlags srcAccessMask
175 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
176 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
177 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
178 **srcBuffer, // VkBuffer buffer
179 0u, // VkDeviceSize offset
180 VK_WHOLE_SIZE, // VkDeviceSize size
182 vk.cmdPipelineBarrier(targetCmdBuffer,
183 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
184 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
185 (vk::VkDependencyFlags) 0,
186 0, (const vk::VkMemoryBarrier *) DE_NULL,
187 1, &startBufferBarrier,
188 0, (const vk::VkImageMemoryBarrier *) DE_NULL);
190 vk.cmdFillBuffer(targetCmdBuffer, **srcBuffer, 0u, VK_WHOLE_SIZE, m_fillValue);
193 // Barrier to change accessMask to transfer read bit for source buffer
194 const vk::VkBufferMemoryBarrier startCopyBufferBarrier =
196 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
197 DE_NULL, // const void* pNext
198 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
199 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
200 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
201 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
202 **srcBuffer, // VkBuffer buffer
203 0u, // VkDeviceSize offset
204 VK_WHOLE_SIZE, // VkDeviceSize size
207 // Start image barrier for destination image.
208 const vk::VkImageMemoryBarrier startImgBarrier =
210 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
211 DE_NULL, // const void* pNext
212 0, // VkAccessFlags srcAccessMask
213 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
214 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
215 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
216 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
217 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
218 **colorImage, // VkImage image
220 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
221 0u, // uint32_t baseMipLevel
222 1u, // uint32_t mipLevels
223 0u, // uint32_t baseArraySlice
224 1u, // uint32_t subresourceRange
228 vk.cmdPipelineBarrier(targetCmdBuffer,
229 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
230 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
231 (vk::VkDependencyFlags)0,
232 0, (const vk::VkMemoryBarrier*)DE_NULL,
233 1, &startCopyBufferBarrier,
234 1, &startImgBarrier);
237 // Copy buffer to image
238 const vk::VkImageSubresourceLayers subresourceLayers =
240 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
241 0u, // uint32_t mipLevel
242 0u, // uint32_t baseArrayLayer
243 1u, // uint32_t layerCount
245 const vk::VkOffset3D nullOffset = {0u, 0u, 0u};
246 const vk::VkExtent3D imageExtent = {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
247 const vk::VkBufferImageCopy copyRegion =
249 0ull, // VkDeviceSize srcOffset;
250 0, // uint32_t bufferRowLength
251 0, // uint32_t bufferImageHeight
252 subresourceLayers, // VkImageSubresourceLayers imageSubresource
253 nullOffset, // VkOffset3D imageOffset
254 imageExtent, // VkExtent3D imageExtent
256 vk.cmdCopyBufferToImage(targetCmdBuffer, **srcBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
259 const vk::VkImageMemoryBarrier endImgBarrier =
261 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
262 DE_NULL, // const void* pNext
263 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
264 vk::VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask
265 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
266 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout
267 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
268 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
269 **colorImage, // VkImage image
271 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
272 0u, // uint32_t baseMipLevel
273 1u, // uint32_t mipLevels
274 0u, // uint32_t baseArraySlice
275 1u, // uint32_t subresourceRange
278 vk.cmdPipelineBarrier(targetCmdBuffer,
279 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
280 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
281 (vk::VkDependencyFlags)0,
282 0, (const vk::VkMemoryBarrier*)DE_NULL,
283 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
287 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
289 endCommandBuffer(vk, *secondaryCmdBuffer);
290 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
293 endCommandBuffer(vk, *cmdBuffer);
295 // Submit command buffer
296 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
297 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
300 ctx.getTestContext().getLog()
301 << tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
303 // Validate resulting image
304 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
305 return tcu::TestStatus::pass("Everything went OK");
307 return tcu::TestStatus::fail("Something went really wrong");
310 tcu::TestCaseGroup* createCopyBufferToImageTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
317 const ValidationData data;
321 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
322 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
323 { tcu::Vec4(0.0f), tcu::Vec4(0.0f),
324 tcu::Vec4(0.0f), tcu::Vec4(0.0f), }
329 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
330 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
331 { tcu::Vec4(1.0f), tcu::Vec4(1.0f),
332 tcu::Vec4(1.0f), tcu::Vec4(1.0f), }
337 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
338 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
339 { tcu::Vec4(0.2f), tcu::Vec4(0.2f),
340 tcu::Vec4(0.2f), tcu::Vec4(0.2f), }
345 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
346 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
347 { tcu::Vec4(0.55f), tcu::Vec4(0.55f),
348 tcu::Vec4(0.55f), tcu::Vec4(0.55f), }
353 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
354 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
355 { tcu::Vec4(0.82f), tcu::Vec4(0.82f),
356 tcu::Vec4(0.82f), tcu::Vec4(0.82f), }
361 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
362 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
363 { tcu::Vec4(0.96f), tcu::Vec4(0.96f),
364 tcu::Vec4(0.96f), tcu::Vec4(0.96f), }
369 de::MovePtr<tcu::TestCaseGroup> copyStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Copy Buffer To Image Tests with static input"));
371 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
373 const std::string name = "copy_" + de::toString(ndx + 1);
374 copyStaticTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), testData[ndx].fillValue.uint, testData[ndx].data, cmdBufferType));
377 /* Add a few randomized tests */
378 de::MovePtr<tcu::TestCaseGroup> copyRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Copy Buffer To Image Tests with random input"));
379 const int testCount = 10;
380 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
381 for (int ndx = 0; ndx < testCount; ++ndx)
383 const std::string name = "copy_" + de::toString(ndx + 1);
388 } fillValue = { rnd.getFloat(0.0, 1.0f) };
390 const tcu::Vec4 refValue (fillValue.flt);
391 const tcu::Vec4 vec0 = tcu::randomVec4(rnd);
392 const tcu::Vec4 vec1 = tcu::randomVec4(rnd);
393 const tcu::Vec4 vec2 = tcu::randomVec4(rnd);
394 const tcu::Vec4 vec3 = tcu::randomVec4(rnd);
396 ValidationData data =
398 { vec0, vec1, vec2, vec3 },
399 { refValue, refValue, refValue, refValue }
401 copyRandomTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), fillValue.uint, data, cmdBufferType));
404 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
405 std::string groupDesc = "Copy Buffer To Image Tests with " + groupName + " command buffer";
406 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
407 copyTests->addChild(copyStaticTests.release());
408 copyTests->addChild(copyRandomTests.release());
409 return copyTests.release();
414 tcu::TestCaseGroup* createCopyBufferToImageTests (tcu::TestContext& testCtx)
416 de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "copy_buffer_to_image", "Copy Buffer To Image Tests"));
418 clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_PRIMARY));
419 clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_SECONDARY));
421 return clearTests.release();