1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 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 Protected content copy buffer to image tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemCopyBufferToImageTests.hpp"
26
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuVectorUtil.hpp"
31
32 #include "vkPrograms.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkCmdUtil.hpp"
38
39 #include "vktProtectedMemContext.hpp"
40 #include "vktProtectedMemUtils.hpp"
41 #include "vktProtectedMemImageValidator.hpp"
42
43 namespace vkt
44 {
45 namespace ProtectedMem
46 {
47
48 namespace
49 {
50
51 enum {
52 BUFFER_SIZE = 256,
53 RENDER_WIDTH = 8,
54 RENDER_HEIGHT = 8,
55 };
56
57 class CopyBufferToImageTestInstance : public ProtectedTestInstance
58 {
59 public:
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);
66
67 private:
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;
73 };
74
75 class CopyBufferToImageTestCase : public TestCase
76 {
77 public:
CopyBufferToImageTestCase(tcu::TestContext & testCtx,const std::string & name,deUint32 fillValue,ValidationData data,CmdBufferType cmdBufferType)78 CopyBufferToImageTestCase (tcu::TestContext& testCtx,
79 const std::string& name,
80 deUint32 fillValue,
81 ValidationData data,
82 CmdBufferType cmdBufferType)
83 : TestCase (testCtx, name, "Copy buffer to image.")
84 , m_fillValue (fillValue)
85 , m_refData (data)
86 , m_validator (vk::VK_FORMAT_R32G32B32A32_SFLOAT)
87 , m_cmdBufferType (cmdBufferType)
88 {
89 }
90
~CopyBufferToImageTestCase(void)91 virtual ~CopyBufferToImageTestCase (void) {}
createInstance(Context & ctx) const92 virtual TestInstance* createInstance (Context& ctx) const
93 {
94 return new CopyBufferToImageTestInstance(ctx, m_fillValue, m_refData, m_validator, m_cmdBufferType);
95 }
initPrograms(vk::SourceCollections & programCollection) const96 virtual void initPrograms (vk::SourceCollections& programCollection) const
97 {
98 m_validator.initPrograms(programCollection);
99 }
checkSupport(Context & context) const100 virtual void checkSupport (Context& context) const
101 {
102 checkProtectedQueueSupport(context);
103 #ifdef CTS_USES_VULKANSC
104 if (m_cmdBufferType == CMD_BUFFER_SECONDARY && context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
105 TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
106 #endif // CTS_USES_VULKANSC
107 }
108 private:
109 deUint32 m_fillValue;
110 ValidationData m_refData;
111 ImageValidator m_validator;
112 CmdBufferType m_cmdBufferType;
113 };
114
CopyBufferToImageTestInstance(Context & ctx,const deUint32 fillValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)115 CopyBufferToImageTestInstance::CopyBufferToImageTestInstance (Context& ctx,
116 const deUint32 fillValue,
117 const ValidationData& refData,
118 const ImageValidator& validator,
119 const CmdBufferType cmdBufferType)
120 : ProtectedTestInstance (ctx)
121 , m_imageFormat (vk::VK_FORMAT_R32G32B32A32_SFLOAT)
122 , m_fillValue (fillValue)
123 , m_refData (refData)
124 , m_validator (validator)
125 , m_cmdBufferType (cmdBufferType)
126 {
127 }
128
iterate()129 tcu::TestStatus CopyBufferToImageTestInstance::iterate()
130 {
131 ProtectedContext& ctx (m_protectedContext);
132 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
133 const vk::VkDevice device = ctx.getDevice();
134 const vk::VkQueue queue = ctx.getQueue();
135 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
136
137 // Create destination image
138 de::MovePtr<vk::ImageWithMemory> colorImage = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
139 RENDER_WIDTH, RENDER_HEIGHT,
140 m_imageFormat,
141 vk::VK_IMAGE_USAGE_SAMPLED_BIT|vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
142 de::MovePtr<vk::BufferWithMemory> srcBuffer (makeBuffer(ctx,
143 PROTECTION_ENABLED,
144 queueFamilyIndex,
145 (deUint32)(BUFFER_SIZE * sizeof(deUint32)),
146 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
147 | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT
148 | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
149 vk::MemoryRequirement::Protected));
150
151 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
152 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
153 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
154 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
155
156 // Begin cmd buffer
157 beginCommandBuffer(vk, *cmdBuffer);
158
159 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
160 {
161 // Begin secondary command buffer
162 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo =
163 {
164 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType
165 DE_NULL, // pNext
166 DE_NULL, // renderPass
167 0u, // subpass
168 DE_NULL, // framebuffer
169 VK_FALSE, // occlusionQueryEnable
170 (vk::VkQueryControlFlags)0u, // queryFlags
171 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
172 };
173 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
174 }
175
176 // Start src buffer barrier
177 {
178 const vk::VkBufferMemoryBarrier startBufferBarrier =
179 {
180 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
181 DE_NULL, // const void* pNext
182 0, // VkAccessFlags srcAccessMask
183 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
184 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
185 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
186 **srcBuffer, // VkBuffer buffer
187 0u, // VkDeviceSize offset
188 VK_WHOLE_SIZE, // VkDeviceSize size
189 };
190 vk.cmdPipelineBarrier(targetCmdBuffer,
191 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
192 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
193 (vk::VkDependencyFlags) 0,
194 0, (const vk::VkMemoryBarrier *) DE_NULL,
195 1, &startBufferBarrier,
196 0, (const vk::VkImageMemoryBarrier *) DE_NULL);
197 }
198 vk.cmdFillBuffer(targetCmdBuffer, **srcBuffer, 0u, VK_WHOLE_SIZE, m_fillValue);
199
200 {
201 // Barrier to change accessMask to transfer read bit for source buffer
202 const vk::VkBufferMemoryBarrier startCopyBufferBarrier =
203 {
204 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType
205 DE_NULL, // const void* pNext
206 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask
207 vk::VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask
208 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
209 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
210 **srcBuffer, // VkBuffer buffer
211 0u, // VkDeviceSize offset
212 VK_WHOLE_SIZE, // VkDeviceSize size
213 };
214
215 // Start image barrier for destination image.
216 const vk::VkImageMemoryBarrier startImgBarrier =
217 {
218 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
219 DE_NULL, // const void* pNext
220 0, // VkAccessFlags srcAccessMask
221 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask
222 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout
223 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout
224 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
225 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
226 **colorImage, // VkImage image
227 {
228 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
229 0u, // uint32_t baseMipLevel
230 1u, // uint32_t mipLevels
231 0u, // uint32_t baseArraySlice
232 1u, // uint32_t subresourceRange
233 }
234 };
235
236 vk.cmdPipelineBarrier(targetCmdBuffer,
237 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
238 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
239 (vk::VkDependencyFlags)0,
240 0, (const vk::VkMemoryBarrier*)DE_NULL,
241 1, &startCopyBufferBarrier,
242 1, &startImgBarrier);
243 }
244
245 // Copy buffer to image
246 const vk::VkImageSubresourceLayers subresourceLayers =
247 {
248 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
249 0u, // uint32_t mipLevel
250 0u, // uint32_t baseArrayLayer
251 1u, // uint32_t layerCount
252 };
253 const vk::VkOffset3D nullOffset = {0u, 0u, 0u};
254 const vk::VkExtent3D imageExtent = {(deUint32)RENDER_WIDTH, (deUint32)RENDER_HEIGHT, 1u};
255 const vk::VkBufferImageCopy copyRegion =
256 {
257 0ull, // VkDeviceSize srcOffset;
258 0, // uint32_t bufferRowLength
259 0, // uint32_t bufferImageHeight
260 subresourceLayers, // VkImageSubresourceLayers imageSubresource
261 nullOffset, // VkOffset3D imageOffset
262 imageExtent, // VkExtent3D imageExtent
263 };
264 vk.cmdCopyBufferToImage(targetCmdBuffer, **srcBuffer, **colorImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region);
265
266 {
267 const vk::VkImageMemoryBarrier endImgBarrier =
268 {
269 vk::VK_STRUCTURE_TYPE_IMAGE_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 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout
274 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout newLayout
275 queueFamilyIndex, // uint32_t srcQueueFamilyIndex
276 queueFamilyIndex, // uint32_t dstQueueFamilyIndex
277 **colorImage, // VkImage image
278 {
279 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask
280 0u, // uint32_t baseMipLevel
281 1u, // uint32_t mipLevels
282 0u, // uint32_t baseArraySlice
283 1u, // uint32_t subresourceRange
284 }
285 };
286 vk.cmdPipelineBarrier(targetCmdBuffer,
287 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
288 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
289 (vk::VkDependencyFlags)0,
290 0, (const vk::VkMemoryBarrier*)DE_NULL,
291 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
292 1, &endImgBarrier);
293 }
294
295 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
296 {
297 endCommandBuffer(vk, *secondaryCmdBuffer);
298 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
299 }
300
301 endCommandBuffer(vk, *cmdBuffer);
302
303 // Submit command buffer
304 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
305 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
306
307 // Log out test data
308 ctx.getTestContext().getLog()
309 << tcu::TestLog::Message << "Fill value: " << m_fillValue << tcu::TestLog::EndMessage;
310
311 // Validate resulting image
312 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
313 return tcu::TestStatus::pass("Everything went OK");
314 else
315 return tcu::TestStatus::fail("Something went really wrong");
316 }
317
createCopyBufferToImageTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)318 tcu::TestCaseGroup* createCopyBufferToImageTests (tcu::TestContext& testCtx, CmdBufferType cmdBufferType)
319 {
320 struct {
321 const union {
322 float flt;
323 deUint32 uint;
324 } fillValue;
325 const ValidationData data;
326 } testData[] = {
327 { { 0.0f },
328 {
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(0.0f), tcu::Vec4(0.0f),
332 tcu::Vec4(0.0f), tcu::Vec4(0.0f), }
333 }
334 },
335 { { 1.0f },
336 {
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(1.0f), tcu::Vec4(1.0f),
340 tcu::Vec4(1.0f), tcu::Vec4(1.0f), }
341 }
342 },
343 { { 0.2f },
344 {
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.2f), tcu::Vec4(0.2f),
348 tcu::Vec4(0.2f), tcu::Vec4(0.2f), }
349 }
350 },
351 { { 0.55f },
352 {
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.55f), tcu::Vec4(0.55f),
356 tcu::Vec4(0.55f), tcu::Vec4(0.55f), }
357 }
358 },
359 { { 0.82f },
360 {
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.82f), tcu::Vec4(0.82f),
364 tcu::Vec4(0.82f), tcu::Vec4(0.82f), }
365 }
366 },
367 { { 0.96f },
368 {
369 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
370 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
371 { tcu::Vec4(0.96f), tcu::Vec4(0.96f),
372 tcu::Vec4(0.96f), tcu::Vec4(0.96f), }
373 }
374 },
375 };
376
377 de::MovePtr<tcu::TestCaseGroup> copyStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Copy Buffer To Image Tests with static input"));
378
379 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
380 {
381 const std::string name = "copy_" + de::toString(ndx + 1);
382 copyStaticTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), testData[ndx].fillValue.uint, testData[ndx].data, cmdBufferType));
383 }
384
385 /* Add a few randomized tests */
386 de::MovePtr<tcu::TestCaseGroup> copyRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Copy Buffer To Image Tests with random input"));
387 const int testCount = 10;
388 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
389 for (int ndx = 0; ndx < testCount; ++ndx)
390 {
391 const std::string name = "copy_" + de::toString(ndx + 1);
392
393 const union {
394 float flt;
395 deUint32 uint;
396 } fillValue = { rnd.getFloat(0.0, 1.0f) };
397
398 const tcu::Vec4 refValue (fillValue.flt);
399 const tcu::Vec4 vec0 = tcu::randomVec4(rnd);
400 const tcu::Vec4 vec1 = tcu::randomVec4(rnd);
401 const tcu::Vec4 vec2 = tcu::randomVec4(rnd);
402 const tcu::Vec4 vec3 = tcu::randomVec4(rnd);
403
404 ValidationData data =
405 {
406 { vec0, vec1, vec2, vec3 },
407 { refValue, refValue, refValue, refValue }
408 };
409 copyRandomTests->addChild(new CopyBufferToImageTestCase(testCtx, name.c_str(), fillValue.uint, data, cmdBufferType));
410 }
411
412 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
413 std::string groupDesc = "Copy Buffer To Image Tests with " + groupName + " command buffer";
414 de::MovePtr<tcu::TestCaseGroup> copyTests (new tcu::TestCaseGroup(testCtx, groupName.c_str(), groupDesc.c_str()));
415 copyTests->addChild(copyStaticTests.release());
416 copyTests->addChild(copyRandomTests.release());
417 return copyTests.release();
418 }
419
420 } // anonymous
421
createCopyBufferToImageTests(tcu::TestContext & testCtx)422 tcu::TestCaseGroup* createCopyBufferToImageTests (tcu::TestContext& testCtx)
423 {
424 de::MovePtr<tcu::TestCaseGroup> clearTests (new tcu::TestCaseGroup(testCtx, "copy_buffer_to_image", "Copy Buffer To Image Tests"));
425
426 clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_PRIMARY));
427 clearTests->addChild(createCopyBufferToImageTests(testCtx, CMD_BUFFER_SECONDARY));
428
429 return clearTests.release();
430 }
431
432 } // ProtectedMem
433 } // vkt
434