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