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 render pass load tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktProtectedMemAttachmentLoadTests.hpp"
26
27 #include "deRandom.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuVector.hpp"
30
31 #include "vkPrograms.hpp"
32 #include "vktTestCase.hpp"
33 #include "vktTestGroupUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkCmdUtil.hpp"
37
38 #include "vktProtectedMemContext.hpp"
39 #include "vktProtectedMemUtils.hpp"
40 #include "vktProtectedMemImageValidator.hpp"
41
42 namespace vkt
43 {
44 namespace ProtectedMem
45 {
46
47 namespace
48 {
49
50 enum {
51 RENDER_WIDTH = 128,
52 RENDER_HEIGHT = 128,
53 };
54
55
56 class AttachmentLoadTestInstance : public ProtectedTestInstance
57 {
58 public:
59 AttachmentLoadTestInstance (Context& ctx,
60 const vk::VkClearValue& clearValue,
61 const ValidationData& refData,
62 const ImageValidator& validator);
63 virtual tcu::TestStatus iterate (void);
64
65 private:
66 const vk::VkFormat m_imageFormat;
67 const vk::VkClearValue& m_clearValue;
68 const ValidationData& m_refData;
69 const ImageValidator& m_validator;
70 };
71
72
73 class AttachmentLoadTestCase : public TestCase
74 {
75 public:
AttachmentLoadTestCase(tcu::TestContext & testCtx,const std::string & name,vk::VkClearValue clearValue,ValidationData data)76 AttachmentLoadTestCase (tcu::TestContext& testCtx,
77 const std::string& name,
78 vk::VkClearValue clearValue,
79 ValidationData data)
80 : TestCase (testCtx, name, "Clear on render pass initialization.")
81 , m_clearValue (clearValue)
82 , m_refData (data)
83 {
84 }
85
~AttachmentLoadTestCase(void)86 virtual ~AttachmentLoadTestCase (void) {}
createInstance(Context & ctx) const87 virtual TestInstance* createInstance (Context& ctx) const
88 {
89 return new AttachmentLoadTestInstance(ctx, m_clearValue, m_refData, m_validator);
90 }
initPrograms(vk::SourceCollections & programCollection) const91 virtual void initPrograms (vk::SourceCollections& programCollection) const
92 {
93 m_validator.initPrograms(programCollection);
94 }
95 private:
96 vk::VkClearValue m_clearValue;
97 ValidationData m_refData;
98 ImageValidator m_validator;
99 };
100
AttachmentLoadTestInstance(Context & ctx,const vk::VkClearValue & clearValue,const ValidationData & refData,const ImageValidator & validator)101 AttachmentLoadTestInstance::AttachmentLoadTestInstance (Context& ctx,
102 const vk::VkClearValue& clearValue,
103 const ValidationData& refData,
104 const ImageValidator& validator)
105 : ProtectedTestInstance (ctx)
106 , m_imageFormat (vk::VK_FORMAT_R8G8B8A8_UNORM)
107 , m_clearValue (clearValue)
108 , m_refData (refData)
109 , m_validator (validator)
110 {
111 }
112
iterate()113 tcu::TestStatus AttachmentLoadTestInstance::iterate()
114 {
115 ProtectedContext& ctx (m_protectedContext);
116 const vk::DeviceInterface& vk = ctx.getDeviceInterface();
117 const vk::VkDevice device = ctx.getDevice();
118 const vk::VkQueue queue = ctx.getQueue();
119 const deUint32 queueFamilyIndex = ctx.getQueueFamilyIndex();
120
121 // Create output image
122 de::MovePtr<vk::ImageWithMemory> colorImage (createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
123 RENDER_WIDTH, RENDER_HEIGHT,
124 m_imageFormat,
125 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
126 vk::Unique<vk::VkImageView> colorImageView (createImageView(ctx, **colorImage, m_imageFormat));
127
128 vk::Unique<vk::VkRenderPass> renderPass (createRenderPass(ctx, m_imageFormat));
129 vk::Unique<vk::VkFramebuffer> framebuffer (createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
130 vk::Unique<vk::VkPipelineLayout> pipelineLayout (createPipelineLayout(ctx, 0u, DE_NULL));
131
132 vk::Unique<vk::VkCommandPool> cmdPool (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
133 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
134
135 // Begin cmd buffer
136 beginCommandBuffer(vk, *cmdBuffer);
137
138 // Start image barrier
139 {
140 const vk::VkImageMemoryBarrier startImgBarrier =
141 {
142 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
143 DE_NULL, // pNext
144 0, // srcAccessMask
145 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask
146 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
147 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
148 queueFamilyIndex, // srcQueueFamilyIndex
149 queueFamilyIndex, // dstQueueFamilyIndex
150 **colorImage, // image
151 {
152 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
153 0u, // baseMipLevel
154 1u, // mipLevels
155 0u, // baseArraySlice
156 1u, // subresourceRange
157 }
158 };
159
160 vk.cmdPipelineBarrier(*cmdBuffer,
161 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
162 vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
163 (vk::VkDependencyFlags)0,
164 0, (const vk::VkMemoryBarrier*)DE_NULL,
165 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
166 1, &startImgBarrier);
167 }
168
169 // Image clear
170 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), m_clearValue);
171 endRenderPass(vk, *cmdBuffer);
172
173 {
174 // Image validator reads image in compute shader
175 const vk::VkImageMemoryBarrier endImgBarrier =
176 {
177 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
178 DE_NULL, // pNext
179 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
180 vk::VK_ACCESS_SHADER_READ_BIT, // dstAccessMask
181 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
182 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // newLayout
183 queueFamilyIndex, // srcQueueFamilyIndex
184 queueFamilyIndex, // dstQueueFamilyIndex
185 **colorImage, // image
186 {
187 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
188 0u, // baseMipLevel
189 1u, // mipLevels
190 0u, // baseArraySlice
191 1u, // subresourceRange
192 }
193 };
194 vk.cmdPipelineBarrier(*cmdBuffer,
195 vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
196 vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
197 (vk::VkDependencyFlags)0,
198 0, (const vk::VkMemoryBarrier*)DE_NULL,
199 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
200 1, &endImgBarrier);
201 }
202
203 endCommandBuffer(vk, *cmdBuffer);
204
205 // Submit command buffer
206 const vk::Unique<vk::VkFence> fence (vk::createFence(vk, device));
207 VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
208
209 // Log out test data
210 ctx.getTestContext().getLog()
211 << tcu::TestLog::Message << "Color clear value: " << tcu::Vec4(m_clearValue.color.float32) << tcu::TestLog::EndMessage
212 << tcu::TestLog::Message << "Depth clear value: " << m_clearValue.depthStencil.depth << tcu::TestLog::EndMessage
213 << tcu::TestLog::Message << "Stencil clear value: " << m_clearValue.depthStencil.stencil << tcu::TestLog::EndMessage;
214
215 // Validate resulting image
216 if (m_validator.validateImage(ctx, m_refData, **colorImage, m_imageFormat, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL))
217 return tcu::TestStatus::pass("Everything went OK");
218 else
219 return tcu::TestStatus::fail("Something went really wrong");
220 }
221
222 } // anonymous
223
createAttachmentLoadTests(tcu::TestContext & testCtx)224 tcu::TestCaseGroup* createAttachmentLoadTests (tcu::TestContext& testCtx)
225 {
226 struct {
227 const vk::VkClearValue clearValue;
228 const ValidationData data;
229 } testData[] = {
230 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
231 {
232 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
233 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
234 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
235 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
236 }
237 },
238 { vk::makeClearValueColorF32(0.0f, 1.0f, 0.0f, 1.0f),
239 {
240 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
241 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
242 { tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
243 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), }
244 }
245 },
246 { vk::makeClearValueColorF32(0.0f, 0.0f, 1.0f, 1.0f),
247 {
248 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
249 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
250 { tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
251 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), }
252 }
253 },
254 { vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f),
255 {
256 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
257 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
258 { tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
259 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), }
260 }
261 },
262 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 1.0f),
263 {
264 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
265 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
266 { tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
267 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), }
268 }
269 },
270 { vk::makeClearValueColorF32(1.0f, 0.0f, 0.0f, 0.0f),
271 {
272 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
273 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
274 { tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
275 tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f), }
276 }
277 },
278 { vk::makeClearValueColorF32(0.1f, 0.2f, 0.3f, 0.0f),
279 {
280 { tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f),
281 tcu::Vec4(0.1f, 0.1f, 0.0f, 0.0f), tcu::Vec4(0.5f, 0.5f, 0.0f, 0.0f), },
282 { tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f),
283 tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), tcu::Vec4(0.1f, 0.2f, 0.3f, 0.0f), }
284 }
285 },
286 };
287
288 de::MovePtr<tcu::TestCaseGroup> loadStaticTests (new tcu::TestCaseGroup(testCtx, "static", "Attachment Load Op Tests with static input"));
289
290 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(testData); ++ndx)
291 {
292 const std::string name = "clear_" + de::toString(ndx + 1);
293 loadStaticTests->addChild(new AttachmentLoadTestCase(testCtx, name.c_str(), testData[ndx].clearValue, testData[ndx].data));
294 }
295
296 /* Add a few randomized tests */
297 de::MovePtr<tcu::TestCaseGroup> loadRandomTests (new tcu::TestCaseGroup(testCtx, "random", "Attachment Load Op Tests with random input"));
298 const int testCount = 10;
299 de::Random rnd (testCtx.getCommandLine().getBaseSeed());
300 for (int ndx = 0; ndx < testCount; ++ndx)
301 {
302 const std::string name = "clear_" + de::toString(ndx + 1);
303 vk::VkClearValue clearValue = vk::makeClearValueColorF32(
304 rnd.getFloat(0.0, 1.0f),
305 rnd.getFloat(0.0, 1.0f),
306 rnd.getFloat(0.0, 1.0f),
307 rnd.getFloat(0.0, 1.0f));
308
309 tcu::Vec4 refValue (clearValue.color.float32[0], clearValue.color.float32[1], clearValue.color.float32[2], clearValue.color.float32[3]);
310 ValidationData data = {
311 { tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
312 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
313 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)),
314 tcu::Vec4(rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f), rnd.getFloat(0.0f, 1.0f)) },
315 { refValue, refValue, refValue, refValue }
316 };
317
318 loadRandomTests->addChild(new AttachmentLoadTestCase(testCtx, name.c_str(), clearValue, data));
319 }
320
321 de::MovePtr<tcu::TestCaseGroup> loadTests (new tcu::TestCaseGroup(testCtx, "load_op", "Attachment Load Op Tests"));
322 loadTests->addChild(loadStaticTests.release());
323 loadTests->addChild(loadRandomTests.release());
324 return loadTests.release();
325 }
326
327 } // ProtectedMem
328 } // vkt
329