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