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