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 memory attachment clear tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemAttachmentClearTests.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 {
53 RENDER_WIDTH = 128,
54 RENDER_HEIGHT = 128,
55 };
56
57 class AttachmentClearTestInstance : public ProtectedTestInstance
58 {
59 public:
60 AttachmentClearTestInstance(Context &ctx, const vk::VkClearValue &clearValue, const ValidationData &refData,
61 const ImageValidator &validator, const CmdBufferType cmdBufferType);
62 virtual tcu::TestStatus iterate(void);
63
64 private:
65 const vk::VkFormat m_imageFormat;
66 const vk::VkClearValue &m_clearValue;
67 const ValidationData &m_refData;
68 const ImageValidator &m_validator;
69 const CmdBufferType m_cmdBufferType;
70 };
71
72 class AttachmentClearTestCase : public TestCase
73 {
74 public:
AttachmentClearTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearValue clearValue,ValidationData data,CmdBufferType cmdBufferType)75 AttachmentClearTestCase(tcu::TestContext &testCtx, const std::string &name, vk::VkClearValue clearValue,
76 ValidationData data, CmdBufferType cmdBufferType)
77 : TestCase(testCtx, name)
78 , m_clearValue(clearValue)
79 , m_refData(data)
80 , m_cmdBufferType(cmdBufferType)
81 {
82 }
83
~AttachmentClearTestCase(void)84 virtual ~AttachmentClearTestCase(void)
85 {
86 }
createInstance(Context & ctx) const87 virtual TestInstance *createInstance(Context &ctx) const
88 {
89 return new AttachmentClearTestInstance(ctx, m_clearValue, m_refData, m_validator, m_cmdBufferType);
90 }
initPrograms(vk::SourceCollections & programCollection) const91 virtual void initPrograms(vk::SourceCollections &programCollection) const
92 {
93 m_validator.initPrograms(programCollection);
94 }
checkSupport(Context & context) const95 virtual void checkSupport(Context &context) const
96 {
97 checkProtectedQueueSupport(context);
98 }
99
100 private:
101 vk::VkClearValue m_clearValue;
102 ValidationData m_refData;
103 ImageValidator m_validator;
104 CmdBufferType m_cmdBufferType;
105 };
106
AttachmentClearTestInstance(Context & ctx,const vk::VkClearValue & clearValue,const ValidationData & refData,const ImageValidator & validator,const CmdBufferType cmdBufferType)107 AttachmentClearTestInstance::AttachmentClearTestInstance(Context &ctx, const vk::VkClearValue &clearValue,
108 const ValidationData &refData, const ImageValidator &validator,
109 const CmdBufferType cmdBufferType)
110 : ProtectedTestInstance(ctx)
111 , m_imageFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
112 , m_clearValue(clearValue)
113 , m_refData(refData)
114 , m_validator(validator)
115 , m_cmdBufferType(cmdBufferType)
116 {
117 }
118
iterate()119 tcu::TestStatus AttachmentClearTestInstance::iterate()
120 {
121 ProtectedContext &ctx(m_protectedContext);
122 const vk::DeviceInterface &vk = ctx.getDeviceInterface();
123 const vk::VkDevice device = ctx.getDevice();
124 const vk::VkQueue queue = ctx.getQueue();
125 const uint32_t queueFamilyIndex = ctx.getQueueFamilyIndex();
126
127 // Create output image
128 de::MovePtr<vk::ImageWithMemory> colorImage(
129 createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex, RENDER_WIDTH, RENDER_HEIGHT, m_imageFormat,
130 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT));
131 vk::Unique<vk::VkImageView> colorImageView(createImageView(ctx, **colorImage, m_imageFormat));
132
133 vk::Unique<vk::VkRenderPass> renderPass(createRenderPass(ctx, m_imageFormat));
134 vk::Unique<vk::VkFramebuffer> framebuffer(
135 createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
136 vk::Unique<vk::VkPipelineLayout> pipelineLayout(createPipelineLayout(ctx, 0u, DE_NULL));
137
138 vk::Unique<vk::VkCommandPool> cmdPool(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
139 vk::Unique<vk::VkCommandBuffer> cmdBuffer(
140 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
141 vk::Unique<vk::VkCommandBuffer> secondaryCmdBuffer(
142 vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
143 vk::VkCommandBuffer targetCmdBuffer = (m_cmdBufferType == CMD_BUFFER_SECONDARY) ? *secondaryCmdBuffer : *cmdBuffer;
144
145 // Begin cmd buffer
146 beginCommandBuffer(vk, *cmdBuffer);
147
148 // Start image barrier
149 {
150 const vk::VkImageMemoryBarrier startImgBarrier = {vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
151 DE_NULL, // pNext
152 0, // srcAccessMask
153 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
154 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
155 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
156 queueFamilyIndex, // srcQueueFamilyIndex
157 queueFamilyIndex, // dstQueueFamilyIndex
158 **colorImage, // image
159 {
160 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
161 0u, // baseMipLevel
162 1u, // mipLevels
163 0u, // baseArraySlice
164 1u, // subresourceRange
165 }};
166
167 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
168 (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier *)DE_NULL, 0,
169 (const vk::VkBufferMemoryBarrier *)DE_NULL, 1, &startImgBarrier);
170 }
171
172 // Image clear to different from input color
173
174 const tcu::Vec4 clearValue(
175 m_clearValue.color.float32[0] < 0.5f ? 1.0f : 0.0f, m_clearValue.color.float32[1] < 0.5f ? 1.0f : 0.0f,
176 m_clearValue.color.float32[2] < 0.5f ? 1.0f : 0.0f, m_clearValue.color.float32[3] < 0.5f ? 1.0f : 0.0f);
177
178 const vk::VkSubpassContents subpassContents = m_cmdBufferType == CMD_BUFFER_SECONDARY ?
179 vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS :
180 vk::VK_SUBPASS_CONTENTS_INLINE;
181 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT), clearValue,
182 subpassContents);
183
184 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
185 {
186 // Begin secondary command buffer
187 const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo = {
188 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // sType
189 DE_NULL, // pNext
190 *renderPass, // renderPass
191 0u, // subpass
192 *framebuffer, // framebuffer
193 VK_FALSE, // occlusionQueryEnable
194 (vk::VkQueryControlFlags)0u, // queryFlags
195 (vk::VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
196 };
197 beginSecondaryCommandBuffer(vk, *secondaryCmdBuffer, bufferInheritanceInfo);
198 }
199
200 {
201 const vk::VkClearAttachment pAttachments = {
202 vk::VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask
203 0u, //uint32_t colorAttachment
204 m_clearValue // VkClearValue clearValue;
205 };
206 const vk::VkRect2D rect2D = vk::makeRect2D(RENDER_WIDTH, RENDER_HEIGHT);
207 const vk::VkClearRect clearRect = {
208 rect2D, // VkRect2D rect;
209 0u, // uint32_t baseArrayLayer;
210 1u // uint32_t layerCount;
211 };
212 vk.cmdClearAttachments(targetCmdBuffer, 1u, &pAttachments, 1u, &clearRect);
213 }
214
215 if (m_cmdBufferType == CMD_BUFFER_SECONDARY)
216 {
217 endCommandBuffer(vk, *secondaryCmdBuffer);
218 vk.cmdExecuteCommands(*cmdBuffer, 1u, &secondaryCmdBuffer.get());
219 }
220
221 endRenderPass(vk, *cmdBuffer);
222
223 {
224 // Image validator reads image in compute shader
225 const vk::VkImageMemoryBarrier endImgBarrier = {vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
226 DE_NULL, // pNext
227 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
228 vk::VK_ACCESS_SHADER_READ_BIT, // dstAccessMask
229 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
230 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
231 queueFamilyIndex, // srcQueueFamilyIndex
232 queueFamilyIndex, // dstQueueFamilyIndex
233 **colorImage, // image
234 {
235 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
236 0u, // baseMipLevel
237 1u, // mipLevels
238 0u, // baseArraySlice
239 1u, // subresourceRange
240 }};
241 vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
242 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0, 0,
243 (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
244 &endImgBarrier);
245 }
246
247 endCommandBuffer(vk, *cmdBuffer);
248
249 // Submit command buffer
250 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
251 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
252
253 // Log out test data
254 ctx.getTestContext().getLog() << tcu::TestLog::Message
255 << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32)
256 << tcu::TestLog::EndMessage << tcu::TestLog::Message
257 << "Depth clear value: " << m_clearValue.depthStencil.depth
258 << tcu::TestLog::EndMessage << tcu::TestLog::Message
259 << "Stencil clear value: " << m_clearValue.depthStencil.stencil
260 << tcu::TestLog::EndMessage;
261
262 // Validate resulting image
263 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat,
264 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
265 return tcu::TestStatus::pass("Everything went OK");
266 else
267 return tcu::TestStatus::fail("Something went really wrong");
268 }
269
createAttachmentClearTests(tcu::TestContext & testCtx,CmdBufferType cmdBufferType)270 tcu::TestCaseGroup *createAttachmentClearTests(tcu::TestContext &testCtx, CmdBufferType cmdBufferType)
271 {
272 struct
273 {
274 const vk::VkClearValue clearValue;
275 const ValidationData data;
276 } testData[] = {
277 {vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
278 {{
279 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
280 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
281 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
282 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
283 },
284 {
285 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
286 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
287 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
288 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
289 }}},
290 {vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f),
291 {{
292 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
293 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
294 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
295 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
296 },
297 {
298 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
299 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
300 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
301 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
302 }}},
303 {vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
304 {{
305 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
306 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
307 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
308 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
309 },
310 {
311 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
312 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
313 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
314 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
315 }}},
316 {vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f),
317 {{
318 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
319 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
320 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
321 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
322 },
323 {
324 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
325 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
326 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
327 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
328 }}},
329 {vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
330 {{
331 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
332 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
333 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
334 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
335 },
336 {
337 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
338 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
339 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
340 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
341 }}},
342 {vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 0.0f),
343 {{
344 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
345 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
346 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
347 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
348 },
349 {
350 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
351 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
352 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
353 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
354 }}},
355 {vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.0f),
356 {{
357 tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
358 tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
359 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f),
360 tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f),
361 },
362 {
363 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
364 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
365 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
366 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
367 }}},
368 };
369
370 // Attachment Clear Op Tests with static input
371 de::MovePtr<tcu::TestCaseGroup> clearStaticTests(new tcu::TestCaseGroup(testCtx, "static"));
372
373 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
374 {
375 const std::string name = "clear_" + de::toString(ndx + 1);
376 clearStaticTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), testData[ndx].clearValue,
377 testData[ndx].data, cmdBufferType));
378 }
379
380 /* Add a few randomized tests */
381 // Attachment Clear Op Tests with random input
382 de::MovePtr<tcu::TestCaseGroup> clearRandomTests(new tcu::TestCaseGroup(testCtx, "random"));
383 const int testCount = 10;
384 de::Random rnd(testCtx.getCommandLine().getBaseSeed());
385 for (int ndx = 0; ndx < testCount; ++ndx)
386 {
387 const std::string name = "clear_" + de::toString(ndx + 1);
388 vk::VkClearValue clearValue = vk::makeClearValueColorVec4(tcu::randomVec4(rnd));
389 const tcu::Vec4 refValue(clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2],
390 clearValue.color.float32[3]);
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);
395
396 ValidationData data = {{vec0, vec1, vec2, vec3}, {refValue, refValue, refValue, refValue}};
397
398 clearRandomTests->addChild(new AttachmentClearTestCase(testCtx, name.c_str(), clearValue, data, cmdBufferType));
399 }
400
401 std::string groupName = getCmdBufferTypeStr(cmdBufferType);
402 de::MovePtr<tcu::TestCaseGroup> clearTests(new tcu::TestCaseGroup(testCtx, groupName.c_str()));
403 clearTests->addChild(clearStaticTests.release());
404 clearTests->addChild(clearRandomTests.release());
405 return clearTests.release();
406 }
407
408 } // namespace
409
createAttachmentClearTests(tcu::TestContext & testCtx)410 tcu::TestCaseGroup *createAttachmentClearTests(tcu::TestContext &testCtx)
411 {
412 de::MovePtr<tcu::TestCaseGroup> clearTests(new tcu::TestCaseGroup(testCtx, "clear_op"));
413
414 clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_PRIMARY));
415 clearTests->addChild(createAttachmentClearTests(testCtx, CMD_BUFFER_SECONDARY));
416
417 return clearTests.release();
418 }
419
420 } // namespace ProtectedMem
421 } // namespace vkt
422