1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 LunarG, Inc.
6 * Copyright (c) 2023 Nintendo
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 Shader Object Link Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktShaderObjectRenderingTests.hpp"
26#include "deUniquePtr.hpp"
27#include "tcuTestCase.hpp"
28#include "vktTestCase.hpp"
29#include "vkCmdUtil.hpp"
30#include "vkImageUtil.hpp"
31#include "vktShaderObjectCreateUtil.hpp"
32#include "vkObjUtil.hpp"
33#include "deRandom.hpp"
34#include "vkBuilderUtil.hpp"
35#include "vkBarrierUtil.hpp"
36#include "tcuTextureUtil.hpp"
37#include "tcuImageCompare.hpp"
38#include "tcuVectorUtil.hpp"
39#include <cmath>
40
41namespace vkt
42{
43namespace ShaderObject
44{
45
46namespace
47{
48
49enum ExtraAttachments {
50	NONE = 0,
51	BEFORE,
52	BETWEEN,
53	AFTER,
54};
55
56enum DummyRenderPass
57{
58	DUMMY_NONE = 0,
59	DUMMY_DYNAMIC,
60	DUMMY_STATIC,
61};
62
63struct TestParams {
64	deUint32 colorAttachmentCount;
65	deUint32 extraAttachmentCount;
66	ExtraAttachments extraAttachments;
67	deUint32 extraFragmentOutputCount;
68	ExtraAttachments extraOutputs;
69	bool useDepthAttachment;
70	vk::VkFormat colorFormat;
71	vk::VkFormat depthFormat;
72	bool bindShadersBeforeBeginRendering;
73	DummyRenderPass dummyRenderPass;
74	bool writeGlFragDepth;
75	bool randomColorFormats;
76};
77
78const vk::VkFormat colorFormats[] =
79{
80	vk::VK_FORMAT_R4G4_UNORM_PACK8,
81	vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
82	vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
83	vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
84	vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
85	vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
86	vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
87	vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
88	vk::VK_FORMAT_R8_UNORM,
89	vk::VK_FORMAT_R8_SNORM,
90	vk::VK_FORMAT_R8_USCALED,
91	vk::VK_FORMAT_R8_SSCALED,
92	vk::VK_FORMAT_R8_UINT,
93	vk::VK_FORMAT_R8_SINT,
94	vk::VK_FORMAT_R8_SRGB,
95	vk::VK_FORMAT_R8G8_UNORM,
96	vk::VK_FORMAT_R8G8_SNORM,
97	vk::VK_FORMAT_R8G8_USCALED,
98	vk::VK_FORMAT_R8G8_SSCALED,
99	vk::VK_FORMAT_R8G8_UINT,
100	vk::VK_FORMAT_R8G8_SINT,
101	vk::VK_FORMAT_R8G8_SRGB,
102	vk::VK_FORMAT_R8G8B8_UNORM,
103	vk::VK_FORMAT_R8G8B8_SNORM,
104	vk::VK_FORMAT_R8G8B8_USCALED,
105	vk::VK_FORMAT_R8G8B8_SSCALED,
106	vk::VK_FORMAT_R8G8B8_UINT,
107	vk::VK_FORMAT_R8G8B8_SINT,
108	vk::VK_FORMAT_R8G8B8_SRGB,
109	vk::VK_FORMAT_B8G8R8_UNORM,
110	vk::VK_FORMAT_B8G8R8_SNORM,
111	vk::VK_FORMAT_B8G8R8_USCALED,
112	vk::VK_FORMAT_B8G8R8_SSCALED,
113	vk::VK_FORMAT_B8G8R8_UINT,
114	vk::VK_FORMAT_B8G8R8_SINT,
115	vk::VK_FORMAT_B8G8R8_SRGB,
116	vk::VK_FORMAT_R8G8B8A8_UNORM,
117	vk::VK_FORMAT_R8G8B8A8_SNORM,
118	vk::VK_FORMAT_R8G8B8A8_USCALED,
119	vk::VK_FORMAT_R8G8B8A8_SSCALED,
120	vk::VK_FORMAT_R8G8B8A8_UINT,
121	vk::VK_FORMAT_R8G8B8A8_SINT,
122	vk::VK_FORMAT_R8G8B8A8_SRGB,
123	vk::VK_FORMAT_B8G8R8A8_UNORM,
124	vk::VK_FORMAT_B8G8R8A8_SNORM,
125	vk::VK_FORMAT_B8G8R8A8_USCALED,
126	vk::VK_FORMAT_B8G8R8A8_SSCALED,
127	vk::VK_FORMAT_B8G8R8A8_UINT,
128	vk::VK_FORMAT_B8G8R8A8_SINT,
129	vk::VK_FORMAT_B8G8R8A8_SRGB,
130	vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
131	vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
132	vk::VK_FORMAT_A8B8G8R8_USCALED_PACK32,
133	vk::VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
134	vk::VK_FORMAT_A8B8G8R8_UINT_PACK32,
135	vk::VK_FORMAT_A8B8G8R8_SINT_PACK32,
136	vk::VK_FORMAT_A8B8G8R8_SRGB_PACK32,
137	vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
138	vk::VK_FORMAT_A2R10G10B10_SNORM_PACK32,
139	vk::VK_FORMAT_A2R10G10B10_USCALED_PACK32,
140	vk::VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
141	vk::VK_FORMAT_A2R10G10B10_UINT_PACK32,
142	vk::VK_FORMAT_A2R10G10B10_SINT_PACK32,
143	vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
144	vk::VK_FORMAT_A2B10G10R10_SNORM_PACK32,
145	vk::VK_FORMAT_A2B10G10R10_USCALED_PACK32,
146	vk::VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
147	vk::VK_FORMAT_A2B10G10R10_UINT_PACK32,
148	vk::VK_FORMAT_A2B10G10R10_SINT_PACK32,
149	vk::VK_FORMAT_R16_UNORM,
150	vk::VK_FORMAT_R16_SNORM,
151	vk::VK_FORMAT_R16_USCALED,
152	vk::VK_FORMAT_R16_SSCALED,
153	vk::VK_FORMAT_R16_UINT,
154	vk::VK_FORMAT_R16_SINT,
155	vk::VK_FORMAT_R16_SFLOAT,
156	vk::VK_FORMAT_R16G16_UNORM,
157	vk::VK_FORMAT_R16G16_SNORM,
158	vk::VK_FORMAT_R16G16_USCALED,
159	vk::VK_FORMAT_R16G16_SSCALED,
160	vk::VK_FORMAT_R16G16_UINT,
161	vk::VK_FORMAT_R16G16_SINT,
162	vk::VK_FORMAT_R16G16_SFLOAT,
163	vk::VK_FORMAT_R16G16B16_UNORM,
164	vk::VK_FORMAT_R16G16B16_SNORM,
165	vk::VK_FORMAT_R16G16B16_USCALED,
166	vk::VK_FORMAT_R16G16B16_SSCALED,
167	vk::VK_FORMAT_R16G16B16_UINT,
168	vk::VK_FORMAT_R16G16B16_SINT,
169	vk::VK_FORMAT_R16G16B16_SFLOAT,
170	vk::VK_FORMAT_R16G16B16A16_UNORM,
171	vk::VK_FORMAT_R16G16B16A16_SNORM,
172	vk::VK_FORMAT_R16G16B16A16_USCALED,
173	vk::VK_FORMAT_R16G16B16A16_SSCALED,
174	vk::VK_FORMAT_R16G16B16A16_UINT,
175	vk::VK_FORMAT_R16G16B16A16_SINT,
176	vk::VK_FORMAT_R16G16B16A16_SFLOAT,
177	vk::VK_FORMAT_R32_UINT,
178	vk::VK_FORMAT_R32_SINT,
179	vk::VK_FORMAT_R32_SFLOAT,
180	vk::VK_FORMAT_R32G32_UINT,
181	vk::VK_FORMAT_R32G32_SINT,
182	vk::VK_FORMAT_R32G32_SFLOAT,
183	vk::VK_FORMAT_R32G32B32_UINT,
184	vk::VK_FORMAT_R32G32B32_SINT,
185	vk::VK_FORMAT_R32G32B32_SFLOAT,
186	vk::VK_FORMAT_R32G32B32A32_UINT,
187	vk::VK_FORMAT_R32G32B32A32_SINT,
188	vk::VK_FORMAT_R32G32B32A32_SFLOAT,
189};
190
191const vk::VkFormat randomColorFormats[] =
192{
193	vk::VK_FORMAT_R8_UNORM,
194	vk::VK_FORMAT_R8_SNORM,
195	vk::VK_FORMAT_R8G8_UNORM,
196	vk::VK_FORMAT_R8G8_SNORM,
197	vk::VK_FORMAT_R8G8B8A8_UNORM,
198	vk::VK_FORMAT_R8G8B8A8_SNORM,
199	vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
200	vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
201	vk::VK_FORMAT_R16_UNORM,
202	vk::VK_FORMAT_R16_SNORM,
203	vk::VK_FORMAT_R16G16_UNORM,
204	vk::VK_FORMAT_R16G16_SNORM,
205	vk::VK_FORMAT_R16G16_SFLOAT,
206	vk::VK_FORMAT_R16G16B16_UNORM,
207	vk::VK_FORMAT_R16G16B16_SNORM,
208	vk::VK_FORMAT_R16G16B16_SFLOAT,
209	vk::VK_FORMAT_R16G16B16A16_UNORM,
210	vk::VK_FORMAT_R16G16B16A16_SNORM,
211	vk::VK_FORMAT_R16G16B16A16_SFLOAT,
212	vk::VK_FORMAT_R32_SFLOAT,
213	vk::VK_FORMAT_R32G32_SFLOAT,
214	vk::VK_FORMAT_R32G32B32_SFLOAT,
215	vk::VK_FORMAT_R32G32B32A32_SFLOAT,
216};
217
218de::MovePtr<tcu::TextureLevel> readDepthAttachment (const vk::DeviceInterface&	vk,
219													vk::VkDevice				device,
220													vk::VkQueue					queue,
221													deUint32					queueFamilyIndex,
222													vk::Allocator&				allocator,
223													vk::VkImage					image,
224													vk::VkFormat				format,
225													const tcu::UVec2&			renderSize,
226													vk::VkImageLayout			currentLayout)
227{
228	vk::Move<vk::VkBuffer>					buffer;
229	de::MovePtr<vk::Allocation>				bufferAlloc;
230	vk::Move<vk::VkCommandPool>				cmdPool;
231	vk::Move<vk::VkCommandBuffer>			cmdBuffer;
232
233	tcu::TextureFormat				retFormat		(tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
234	tcu::TextureFormat				bufferFormat	(tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
235	const vk::VkImageAspectFlags	barrierAspect	= vk::VK_IMAGE_ASPECT_DEPTH_BIT | (mapVkFormat(format).order == tcu::TextureFormat::DS ? vk::VK_IMAGE_ASPECT_STENCIL_BIT : (vk::VkImageAspectFlagBits)0);
236
237	switch (format)
238	{
239	case vk::VK_FORMAT_D16_UNORM:
240	case vk::VK_FORMAT_D16_UNORM_S8_UINT:
241		bufferFormat.type = retFormat.type = tcu::TextureFormat::UNORM_INT16;
242		break;
243	case vk::VK_FORMAT_D24_UNORM_S8_UINT:
244	case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
245		retFormat.type = tcu::TextureFormat::UNORM_INT24;
246		// vkCmdCopyBufferToImage copies D24 data to 32-bit pixels.
247		bufferFormat.type = tcu::TextureFormat::UNSIGNED_INT_24_8_REV;
248		break;
249	case vk::VK_FORMAT_D32_SFLOAT:
250	case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
251		bufferFormat.type = retFormat.type = tcu::TextureFormat::FLOAT;
252		break;
253	default:
254		TCU_FAIL("unrecognized format");
255	}
256
257	const vk::VkDeviceSize				pixelDataSize	= renderSize.x() * renderSize.y() * bufferFormat.getPixelSize();
258	de::MovePtr<tcu::TextureLevel>	resultLevel		(new tcu::TextureLevel(retFormat, renderSize.x(), renderSize.y()));
259
260	// Create destination buffer
261	{
262		const vk::VkBufferCreateInfo bufferParams =
263		{
264			vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
265			DE_NULL,									// const void*			pNext;
266			0u,											// VkBufferCreateFlags	flags;
267			pixelDataSize,								// VkDeviceSize			size;
268			vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
269			vk::VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
270			0u,											// deUint32				queueFamilyIndexCount;
271			DE_NULL										// const deUint32*		pQueueFamilyIndices;
272		};
273
274		buffer		= createBuffer(vk, device, &bufferParams);
275		bufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), vk::MemoryRequirement::HostVisible);
276		VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
277	}
278
279	// Create command pool and buffer
280	cmdPool		= createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
281	cmdBuffer	= allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
282
283	beginCommandBuffer(vk, *cmdBuffer);
284	copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()), vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, currentLayout, 1u, barrierAspect, vk::VK_IMAGE_ASPECT_DEPTH_BIT);
285	endCommandBuffer(vk, *cmdBuffer);
286
287	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
288
289	// Read buffer data
290	invalidateAlloc(vk, device, *bufferAlloc);
291	tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(bufferFormat, resultLevel->getSize(), bufferAlloc->getHostPtr()));
292
293	return resultLevel;
294}
295
296class ShaderObjectRenderingInstance : public vkt::TestInstance
297{
298public:
299							ShaderObjectRenderingInstance	(Context& context, const TestParams& params)
300															: vkt::TestInstance	(context)
301															, m_params			(params)
302															{}
303	virtual					~ShaderObjectRenderingInstance	(void) {}
304
305	tcu::TestStatus			iterate							(void) override;
306private:
307	void					beginRendering					(vk::VkCommandBuffer cmdBuffer);
308	void					createDummyImage				(void);
309	void					createDummyRenderPass			(void);
310	void					setColorFormats					(const vk::InstanceDriver& vki);
311	void					generateExpectedImage			(const tcu::PixelBufferAccess& outputImage, const deUint32 width, const deUint32 height, deUint32 attachmentIndex);
312
313	TestParams								m_params;
314
315	const vk::VkRect2D						m_renderArea = vk::makeRect2D(0, 0, 32, 32);
316	std::vector<vk::VkFormat>				m_colorFormats;
317	std::vector<vk::Move<vk::VkImageView>>	m_colorImageViews;
318	vk::Move<vk::VkImageView>				m_depthImageView;
319
320	de::MovePtr<vk::ImageWithMemory>		m_dummyImage;
321	vk::Move<vk::VkImageView>				m_dummyImageView;
322	vk::Move<vk::VkRenderPass>				m_dummyRenderPass;
323	vk::Move<vk::VkFramebuffer>				m_dummyFramebuffer;
324};
325
326void ShaderObjectRenderingInstance::createDummyImage (void)
327{
328	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
329	const vk::VkDevice					device						= m_context.getDevice();
330	auto&								alloc						= m_context.getDefaultAllocator();
331	const auto							colorSubresourceRange		= makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
332
333	vk::VkFormat format = m_params.colorFormat == vk::VK_FORMAT_R8G8B8A8_UNORM ? vk::VK_FORMAT_R32G32B32A32_SFLOAT : vk::VK_FORMAT_R8G8B8A8_UNORM;
334
335	const vk::VkImageCreateInfo	createInfo =
336	{
337		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
338		DE_NULL,									// const void*				pNext
339		0u,											// VkImageCreateFlags		flags
340		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
341		format,										// VkFormat					format
342		{ 32, 32, 1 },								// VkExtent3D				extent
343		1u,											// uint32_t					mipLevels
344		1u,											// uint32_t					arrayLayers
345		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
346		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
347		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
348		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
349		0,											// uint32_t					queueFamilyIndexCount
350		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
351		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
352	};
353
354	m_dummyImage = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
355	m_dummyImageView = vk::makeImageView(vk, device, **m_dummyImage, vk::VK_IMAGE_VIEW_TYPE_2D, format, colorSubresourceRange);
356}
357
358void ShaderObjectRenderingInstance::createDummyRenderPass (void)
359{
360	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
361	const vk::VkDevice					device						= m_context.getDevice();
362	vk::VkFormat format = m_params.colorFormat == vk::VK_FORMAT_R8G8B8A8_UNORM ? vk::VK_FORMAT_R32G32B32A32_SFLOAT : vk::VK_FORMAT_R8G8B8A8_UNORM;
363	m_dummyRenderPass = vk::makeRenderPass(vk, device, format);
364	m_dummyFramebuffer = vk::makeFramebuffer(vk, device, *m_dummyRenderPass, 1u, &*m_dummyImageView, m_renderArea.extent.width, m_renderArea.extent.height);
365}
366
367vk::VkClearValue getClearValue(const tcu::TextureFormat tcuFormat)
368{
369	const tcu::TextureChannelClass	channelClass = tcu::getTextureChannelClass(tcuFormat.type);
370
371	if (channelClass != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER && channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
372		return vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
373
374	const tcu::IVec4	bits = tcu::min(tcu::getTextureFormatBitDepth(tcuFormat), tcu::IVec4(32));
375	const int			signBit = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? 1 : 0);
376
377	if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
378		return vk::makeClearValueColorU32(0u, 0u, 0u, deUint32((deUint64(1) << (bits[3] - signBit)) - 1));
379
380	return vk::makeClearValueColorI32(0u, 0u, 0u, deInt32((deUint64(1) << (bits[3] - signBit)) - 1));
381}
382
383void ShaderObjectRenderingInstance::beginRendering (vk::VkCommandBuffer cmdBuffer)
384{
385	const vk::DeviceInterface&			vk					= m_context.getDeviceInterface();
386	const vk::VkClearValue				floatClearValue		= vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
387	const vk::VkClearValue				clearDepthValue		= vk::makeClearValueDepthStencil(1.0f, 0u);
388
389	vk::VkRenderingAttachmentInfo colorAttachment
390	{
391		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
392		DE_NULL,												// const void*							pNext;
393		VK_NULL_HANDLE,											// VkImageView							imageView;
394		vk::VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout						imageLayout;
395		vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
396		DE_NULL,												// VkImageView							resolveImageView;
397		vk::VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout						resolveImageLayout;
398		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp					loadOp;
399		vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
400		floatClearValue											// VkClearValue							clearValue;
401	};
402
403	deUint32 outputCount = m_params.colorAttachmentCount + m_params.extraFragmentOutputCount + m_params.extraAttachmentCount;
404	std::vector<vk::VkRenderingAttachmentInfo> colorAttachments(outputCount);
405	deUint32 i = 0;
406	if (m_params.extraOutputs == BEFORE || (m_params.extraOutputs == BETWEEN && m_params.colorAttachmentCount + m_params.extraAttachmentCount == 0))
407	{
408		colorAttachment.imageView = VK_NULL_HANDLE;
409		for (deUint32 j = 0; j < m_params.extraFragmentOutputCount; ++j)
410			colorAttachments[i++] = colorAttachment;
411	}
412	for (deUint32 j = 0; j < m_params.colorAttachmentCount + m_params.extraAttachmentCount; ++j)
413	{
414		if (m_params.extraOutputs == BETWEEN && i == (m_params.colorAttachmentCount + m_params.extraAttachmentCount) / 2 + 1)
415		{
416			colorAttachment.imageView = VK_NULL_HANDLE;
417			for (deUint32 k = 0; k < m_params.extraFragmentOutputCount; ++k)
418				colorAttachments[i++] = colorAttachment;
419		}
420		colorAttachment.imageView = *m_colorImageViews[j];
421		colorAttachment.clearValue = getClearValue(vk::mapVkFormat(m_colorFormats[j]));
422
423		colorAttachments[i++] = colorAttachment;
424	}
425	if (m_params.extraOutputs == AFTER || (m_params.extraOutputs == BETWEEN && m_params.colorAttachmentCount + m_params.extraAttachmentCount == 1))
426	{
427		colorAttachment.imageView = VK_NULL_HANDLE;
428		for (deUint32 j = 0; j < m_params.extraFragmentOutputCount; ++j)
429			colorAttachments[i++] = colorAttachment;
430	}
431
432	vk::VkRenderingAttachmentInfo depthAttachment
433	{
434		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
435		DE_NULL,												// const void*							pNext;
436		*m_depthImageView,										// VkImageView							imageView;
437		vk::VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout						imageLayout;
438		vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
439		DE_NULL,												// VkImageView							resolveImageView;
440		vk::VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout						resolveImageLayout;
441		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp					loadOp;
442		vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
443		clearDepthValue											// VkClearValue							clearValue;
444	};
445
446	vk::VkRenderingInfoKHR renderingInfo
447	{
448		vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
449		DE_NULL,
450		(vk::VkRenderingFlags)0u,									// VkRenderingFlagsKHR					flags;
451		m_renderArea,												// VkRect2D								renderArea;
452		1u,															// deUint32								layerCount;
453		0x0,														// deUint32								viewMask;
454		(deUint32)colorAttachments.size(),							// deUint32								colorAttachmentCount;
455		colorAttachments.data(),									// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
456		m_params.useDepthAttachment ? &depthAttachment : DE_NULL,	// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
457		DE_NULL,													// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
458	};
459
460	vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
461}
462
463void ShaderObjectRenderingInstance::setColorFormats (const vk::InstanceDriver& vki)
464{
465	const auto							physicalDevice = m_context.getPhysicalDevice();
466
467	m_colorFormats.resize(m_params.colorAttachmentCount + m_params.extraAttachmentCount);
468	if (m_params.randomColorFormats)
469	{
470		if (m_colorFormats.size() > 0)
471		{
472			m_colorFormats[0] = m_params.colorFormat;
473		}
474		de::Random random(102030);
475		for (deUint32 i = 1; i < (deUint32)m_colorFormats.size(); ++i)
476		{
477			if (i <= m_params.extraAttachmentCount && m_params.extraAttachments == BEFORE)
478				m_colorFormats[i] = m_params.colorFormat;
479			else
480			{
481				while (true)
482				{
483					// Find random color format, and make sure it is supported
484					vk::VkFormat format = randomColorFormats[random.getUint32() % DE_LENGTH_OF_ARRAY(randomColorFormats)];
485					vk::VkImageFormatProperties	colorImageFormatProperties;
486					const auto colorResult = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0, &colorImageFormatProperties);
487					if (colorResult == vk::VK_SUCCESS)
488					{
489						m_colorFormats[i] = format;
490						break;
491					}
492				}
493			}
494		}
495	}
496	else
497	{
498		for (auto& colorFormat : m_colorFormats)
499			colorFormat = m_params.colorFormat;
500	}
501}
502
503void ShaderObjectRenderingInstance::generateExpectedImage (const tcu::PixelBufferAccess& outputImage, const deUint32 width, const deUint32 height, deUint32 attachmentIndex)
504{
505	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(outputImage.getFormat().type);
506	const vk::VkClearValue			clearValue		= getClearValue(outputImage.getFormat());
507
508	const deUint32					xOffset			= 8;
509	const deUint32					yOffset			= 8;
510
511	if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
512		tcu::clear(outputImage, tcu::UVec4(clearValue.color.uint32));
513	else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
514		tcu::clear(outputImage, tcu::IVec4(clearValue.color.int32));
515	else
516		tcu::clear(outputImage, tcu::Vec4(clearValue.color.float32));
517
518	if ((m_params.extraAttachments == BEFORE && attachmentIndex < m_params.extraAttachmentCount) || (m_params.extraAttachments == BETWEEN && attachmentIndex > m_params.colorAttachmentCount / 2u && attachmentIndex <= m_params.colorAttachmentCount / 2u + m_params.extraAttachmentCount) || (m_params.extraAttachments == AFTER && attachmentIndex >= m_params.colorAttachmentCount))
519		return;
520
521	tcu::Vec4 setColor		= tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
522	tcu::IVec4 setColorInt	= tcu::IVec4(0, 0, 0, 0);
523	tcu::UVec4 setColorUint = tcu::UVec4(0u, 0u, 0u, 0u);
524
525	for (deInt32 i = 0; i < tcu::getNumUsedChannels(outputImage.getFormat().order); ++i)
526	{
527		setColor[i] = 1.0f;
528		setColorInt[i] = 255;
529		setColorUint[i] = 255u;
530	}
531
532	for (deUint32 j = 0; j < height; ++j)
533	{
534		for (deUint32 i = 0; i < width; ++i)
535		{
536			if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
537			{
538				if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
539					outputImage.setPixel(setColorUint, i, j, 0);
540				else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
541					outputImage.setPixel(setColorInt, i, j, 0);
542				else
543					outputImage.setPixel(setColor, i, j, 0);
544			}
545		}
546	}
547}
548
549tcu::TestStatus ShaderObjectRenderingInstance::iterate (void)
550{
551	const vk::VkInstance				instance					= m_context.getInstance();
552	const vk::InstanceDriver			instanceDriver				(m_context.getPlatformInterface(), instance);
553	const vk::DeviceInterface&			vk							= m_context.getDeviceInterface();
554	const vk::VkDevice					device						= m_context.getDevice();
555	const vk::VkQueue					queue						= m_context.getUniversalQueue();
556	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
557	auto&								alloc						= m_context.getDefaultAllocator();
558	tcu::TestLog&						log							= m_context.getTestContext().getLog();
559	const auto							deviceExtensions			= vk::removeUnsupportedShaderObjectExtensions(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
560	const bool							tessellationSupported		= m_context.getDeviceFeatures().tessellationShader;
561	const bool							geometrySupported			= m_context.getDeviceFeatures().geometryShader;
562	const bool							taskSupported				= m_context.getMeshShaderFeatures().taskShader;
563	const bool							meshSupported				= m_context.getMeshShaderFeatures().meshShader;
564
565	const auto							colorSubresourceRange		= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
566	auto								depthSubresourceRange		= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
567	if (m_params.useDepthAttachment && tcu::hasStencilComponent(mapVkFormat(m_params.depthFormat).order))
568		depthSubresourceRange.aspectMask |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
569	const auto							colorSubresourceLayers		= vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
570	vk::VkExtent3D						extent						= { m_renderArea.extent.width, m_renderArea.extent.height, 1};
571
572	setColorFormats(instanceDriver);
573
574	vk::VkImageCreateInfo	createInfo =
575	{
576		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
577		DE_NULL,									// const void*				pNext
578		0u,											// VkImageCreateFlags		flags
579		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
580		vk::VK_FORMAT_UNDEFINED,					// VkFormat					format
581		{ 32, 32, 1 },								// VkExtent3D				extent
582		1u,											// uint32_t					mipLevels
583		1u,											// uint32_t					arrayLayers
584		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
585		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
586		vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
587		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
588		0,											// uint32_t					queueFamilyIndexCount
589		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
590		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
591	};
592
593	const vk::VkImageCreateInfo	depthCreateInfo =
594	{
595		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
596		DE_NULL,									// const void*				pNext
597		0u,											// VkImageCreateFlags		flags
598		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
599		m_params.depthFormat,						// VkFormat					format
600		{ 32, 32, 1 },								// VkExtent3D				extent
601		1u,											// uint32_t					mipLevels
602		1u,											// uint32_t					arrayLayers
603		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
604		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
605		vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	// VkImageUsageFlags		usage
606		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
607		0,											// uint32_t					queueFamilyIndexCount
608		DE_NULL,									// const uint32_t*			pQueueFamilyIndices
609		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
610	};
611
612	deUint32 colorAttachmentCount = m_params.colorAttachmentCount + m_params.extraAttachmentCount;
613	std::vector<de::MovePtr<vk::ImageWithMemory>>	colorImages	(colorAttachmentCount);
614	m_colorImageViews.resize(colorAttachmentCount);
615	for (deUint32 i = 0; i < colorAttachmentCount; ++i)
616	{
617		createInfo.format = m_colorFormats[i];
618		colorImages[i] = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
619		m_colorImageViews[i] = vk::makeImageView(vk, device, **colorImages[i], vk::VK_IMAGE_VIEW_TYPE_2D, createInfo.format, colorSubresourceRange);
620	}
621
622	de::MovePtr<vk::ImageWithMemory>	depthImage;
623	if (m_params.useDepthAttachment)
624	{
625		depthImage = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vk, device, alloc, depthCreateInfo, vk::MemoryRequirement::Any));
626		m_depthImageView = vk::makeImageView(vk, device, **depthImage, vk::VK_IMAGE_VIEW_TYPE_2D, m_params.depthFormat, depthSubresourceRange);
627	}
628
629	std::vector<de::MovePtr<vk::BufferWithMemory>>	colorOutputBuffers;
630	for (deUint32 i = 0; i < colorAttachmentCount; ++i)
631	{
632		const vk::VkDeviceSize				colorOutputBufferSize = m_renderArea.extent.width * m_renderArea.extent.height * tcu::getPixelSize(vk::mapVkFormat(m_colorFormats[i]));
633		colorOutputBuffers.push_back(de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
634			vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible)));
635	}
636
637	const auto&							binaries				= m_context.getBinaryCollection();
638	const auto							vertShader				= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vertDepth"), tessellationSupported, geometrySupported));
639	const auto							fragShader				= vk::createShader(vk, device, vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("fragMulti"), tessellationSupported, geometrySupported));
640
641	const vk::Move<vk::VkCommandPool>	cmdPool					(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
642	const vk::Move<vk::VkCommandBuffer>	cmdBuffer				(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
643
644	vk::beginCommandBuffer(vk, *cmdBuffer);
645
646	if (m_params.dummyRenderPass == DUMMY_DYNAMIC)
647	{
648		createDummyImage();
649		const vk::VkClearValue				clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
650		vk::beginRendering(vk, *cmdBuffer, *m_dummyImageView, m_renderArea, clearValue);
651	}
652	else if (m_params.dummyRenderPass == DUMMY_STATIC)
653	{
654		createDummyImage();
655		createDummyRenderPass();
656		const vk::VkClearValue				clearValue = vk::makeClearValueColor({ 0.0f, 0.0f, 0.0f, 1.0f });
657		vk::beginRenderPass(vk, *cmdBuffer, *m_dummyRenderPass, *m_dummyFramebuffer, m_renderArea, clearValue);
658	}
659
660	if (m_params.bindShadersBeforeBeginRendering)
661		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, *fragShader, taskSupported, meshSupported);
662
663	if (m_params.dummyRenderPass == DUMMY_DYNAMIC)
664	{
665		vk::endRendering(vk, *cmdBuffer);
666	}
667	else if (m_params.dummyRenderPass == DUMMY_STATIC)
668	{
669		vk::endRenderPass(vk, *cmdBuffer);
670	}
671
672	for (const auto& colorImage : colorImages)
673	{
674		vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **colorImage, colorSubresourceRange);
675		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preImageBarrier);
676	}
677
678	if (m_params.useDepthAttachment)
679	{
680		vk::VkImageMemoryBarrier preDepthImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_NONE, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, **depthImage, depthSubresourceRange);
681		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &preDepthImageBarrier);
682	}
683
684	beginRendering(*cmdBuffer);
685	vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
686	vk::VkBool32 colorBlendEnable = VK_FALSE;
687	vk::VkColorBlendEquationEXT		colorBlendEquation = {
688		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	srcColorBlendFactor;
689		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	dstColorBlendFactor;
690		vk::VK_BLEND_OP_ADD,			// VkBlendOp		colorBlendOp;
691		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	srcAlphaBlendFactor;
692		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	dstAlphaBlendFactor;
693		vk::VK_BLEND_OP_ADD,			// VkBlendOp		alphaBlendOp;
694	};
695	vk::VkColorComponentFlags		colorWriteMask = vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT |
696		vk::VK_COLOR_COMPONENT_B_BIT | vk::VK_COLOR_COMPONENT_A_BIT;
697	deUint32 count = colorAttachmentCount + m_params.extraFragmentOutputCount;
698	if (count == 0) ++count;
699	std::vector<vk::VkBool32>					colorBlendEnables	(count, colorBlendEnable);
700	std::vector<vk::VkColorBlendEquationEXT>	colorBlendEquations	(count, colorBlendEquation);
701	std::vector<vk::VkColorComponentFlags>		colorWriteMasks		(count, colorWriteMask);
702	vk.cmdSetColorBlendEnableEXT(*cmdBuffer, 0u, count, colorBlendEnables.data());
703	vk.cmdSetColorBlendEquationEXT(*cmdBuffer, 0u, count, colorBlendEquations.data());
704	vk.cmdSetColorWriteMaskEXT(*cmdBuffer, 0u, count, colorWriteMasks.data());
705	std::vector<vk::VkBool32> colorWriteEnables	(count, VK_TRUE);
706	vk.cmdSetColorWriteEnableEXT(*cmdBuffer, count, colorWriteEnables.data());
707	vk.cmdSetDepthWriteEnable(*cmdBuffer, VK_TRUE);
708	vk.cmdSetDepthTestEnable(*cmdBuffer, VK_TRUE);
709	vk.cmdSetDepthCompareOp(*cmdBuffer, vk::VK_COMPARE_OP_LESS);
710	vk::bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
711	if (!m_params.bindShadersBeforeBeginRendering)
712		vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, *fragShader, taskSupported, meshSupported);
713	vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
714	vk::endRendering(vk, *cmdBuffer);
715
716	for (const auto& colorImage : colorImages)
717	{
718		vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **colorImage, colorSubresourceRange);
719		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
720	}
721
722	if (m_params.useDepthAttachment)
723	{
724		vk::VkImageMemoryBarrier postDepthImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **depthImage, depthSubresourceRange);
725		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postDepthImageBarrier);
726	}
727
728	const vk::VkBufferImageCopy	colorCopyRegion = vk::makeBufferImageCopy(extent, colorSubresourceLayers);
729	for (deUint32 i = 0; i < colorAttachmentCount; ++i)
730		vk.cmdCopyImageToBuffer(*cmdBuffer, **colorImages[i], vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffers[i], 1u, &colorCopyRegion);
731
732	vk::endCommandBuffer(vk, *cmdBuffer);
733
734	vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
735
736	std::vector<tcu::ConstPixelBufferAccess> colorResultBuffers;
737	for (deUint32 i = 0; i < colorAttachmentCount; ++i)
738		colorResultBuffers.push_back(tcu::ConstPixelBufferAccess(vk::mapVkFormat(m_colorFormats[i]), m_renderArea.extent.width, m_renderArea.extent.height, 1, (const void*)colorOutputBuffers[i]->getAllocation().getHostPtr()));
739
740	const deUint32			width	= m_renderArea.extent.width;
741	const deUint32			height	= m_renderArea.extent.height;
742	const deUint32			xOffset = 8;
743	const deUint32			yOffset = 8;
744
745	for (deUint32 k = 0; k < (deUint32)colorImages.size(); ++k)
746	{
747		tcu::TextureLevel					textureLevel	(mapVkFormat(m_colorFormats[k]), width, height);
748		const tcu::PixelBufferAccess		expectedImage	= textureLevel.getAccess();
749		generateExpectedImage(expectedImage, width, height, k);
750
751		if (vk::isFloatFormat(m_colorFormats[k]))
752		{
753			if (!tcu::floatThresholdCompare(log, "Image Comparison", "", expectedImage, colorResultBuffers[k], tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
754				return tcu::TestStatus::fail("Fail");
755		}
756		else
757		{
758			if (!tcu::intThresholdCompare(log, "Image Comparison", "", expectedImage, colorResultBuffers[k], tcu::UVec4(2), tcu::COMPARE_LOG_RESULT))
759				return tcu::TestStatus::fail("Fail");
760		}
761	}
762
763	if (m_params.useDepthAttachment)
764	{
765		const auto depthBuffer = readDepthAttachment(vk, device, queue, queueFamilyIndex, alloc, **depthImage, m_params.depthFormat, tcu::UVec2(m_renderArea.extent.width, m_renderArea.extent.height), vk::VK_IMAGE_LAYOUT_GENERAL);
766		const auto depthAccess = depthBuffer->getAccess();
767
768		const float depthEpsilon = 0.02f;
769		for (deUint32 j = 0; j < height; ++j)
770		{
771			for (deUint32 i = 0; i < width; ++i)
772			{
773				const float depth = depthAccess.getPixDepth(i, j);
774				if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
775				{
776					if (deFloatAbs(depth - 0.5f) > depthEpsilon)
777					{
778						log << tcu::TestLog::Message << "Depth at (" << i << ", " << j << ") is expected to be 0.5, but was (" << depth << ")" << tcu::TestLog::EndMessage;
779						return tcu::TestStatus::fail("Fail");
780					}
781				}
782				else
783				{
784					if (deFloatAbs(depth - 1.0f) > depthEpsilon)
785					{
786						log << tcu::TestLog::Message << "Color at (" << i << ", " << j << ") is expected to be 0.0, but was (" << depth << ")" << tcu::TestLog::EndMessage;
787						return tcu::TestStatus::fail("Fail");
788					}
789				}
790			}
791		}
792	}
793
794	return tcu::TestStatus::pass("Pass");
795}
796
797class ShaderObjectRenderingCase : public vkt::TestCase
798{
799public:
800							ShaderObjectRenderingCase	(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
801														: vkt::TestCase		(testCtx, name)
802														, m_params			(params)
803														{}
804	virtual					~ShaderObjectRenderingCase	(void) {}
805
806	void					checkSupport			(vkt::Context& context) const override;
807	virtual void			initPrograms			(vk::SourceCollections& programCollection) const override;
808	TestInstance*			createInstance			(Context& context) const override { return new ShaderObjectRenderingInstance(context, m_params); }
809private:
810	TestParams m_params;
811};
812
813void ShaderObjectRenderingCase::checkSupport (Context& context) const
814{
815	const auto&		vki				= context.getInstanceInterface();
816	const auto		physicalDevice	= context.getPhysicalDevice();
817	const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
818
819	context.requireDeviceFunctionality("VK_EXT_shader_object");
820
821	if (m_params.colorAttachmentCount + m_params.extraAttachmentCount + m_params.extraFragmentOutputCount > properties.limits.maxColorAttachments)
822		TCU_THROW(NotSupportedError, "Tests uses more color attachments than VkPhysicalDeviceLimits::maxColorAttachments");
823
824	vk::VkImageFormatProperties	colorImageFormatProperties;
825	const auto colorResult = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_params.colorFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0, &colorImageFormatProperties);
826	if (colorResult != vk::VK_SUCCESS)
827		TCU_THROW(NotSupportedError, "Format unsupported for tiling");
828	vk::VkImageFormatProperties	depthImageFormatProperties;
829	if (m_params.useDepthAttachment)
830	{
831		const auto depthResult = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, m_params.depthFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0, &depthImageFormatProperties);
832		if (depthResult != vk::VK_SUCCESS)
833			TCU_THROW(NotSupportedError, "Format unsupported for tiling");
834	}
835}
836
837void ShaderObjectRenderingCase::initPrograms (vk::SourceCollections& programCollection) const
838{
839	std::stringstream vertDepth;
840	std::stringstream fragMulti;
841
842	vertDepth
843		<< "#version 450\n"
844		<< "void main() {\n"
845		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
846		<< "    gl_Position = vec4(pos - 0.5f, 0.5f, 1.0f);\n"
847		<< "}\n";
848
849	fragMulti
850		<< "#version 450\n";
851	deUint32 outputCount = m_params.colorAttachmentCount + m_params.extraFragmentOutputCount;
852	for (deUint32 i = 0; i < outputCount; ++i)
853	{
854		deUint32 j = i;
855		if (m_params.extraAttachments == BEFORE || (m_params.extraAttachments == BETWEEN && i > outputCount / 2))
856			j += m_params.extraAttachmentCount;
857		bool firstWrittenAttachment = (m_params.extraOutputs == BEFORE) ? (i == m_params.extraFragmentOutputCount) : (i == 0);
858		if (vk::isUintFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
859			fragMulti << "layout (location = " << j << ") out uvec4 outColor" << j << ";\n";
860		else if (vk::isIntFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
861			fragMulti << "layout (location = " << j << ") out ivec4 outColor" << j << ";\n";
862		else
863			fragMulti << "layout (location = " << j << ") out vec4 outColor" << j << ";\n";
864	}
865	fragMulti
866		<< "void main() {\n";
867	for (deUint32 i = 0; i < outputCount; ++i)
868	{
869		deUint32 j = i;
870		if (m_params.extraAttachments == BEFORE || (m_params.extraAttachments == BETWEEN && i > outputCount / 2))
871			j += m_params.extraAttachmentCount;
872		bool firstWrittenAttachment = (m_params.extraOutputs == BEFORE) ? (i == m_params.extraFragmentOutputCount) : (i == 0);
873		if (vk::isUintFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
874			fragMulti << "    outColor" << j << " = uvec4(255);\n";
875		else if (vk::isIntFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
876			fragMulti << "    outColor" << j << " = ivec4(255);\n";
877		else
878			fragMulti << "    outColor" << j << " = vec4(1.0f);\n";
879	}
880	if (m_params.writeGlFragDepth)
881		fragMulti
882			<< "    gl_FragDepth = 0.5f;\n";
883	fragMulti
884		<< "}\n";
885
886	programCollection.glslSources.add("vertDepth") << glu::VertexSource(vertDepth.str());
887	programCollection.glslSources.add("fragMulti") << glu::FragmentSource(fragMulti.str());
888}
889
890}
891
892std::string getFormatCaseName(vk::VkFormat format)
893{
894	return de::toLower(de::toString(getFormatStr(format)).substr(10));
895}
896
897tcu::TestCaseGroup* createShaderObjectRenderingTests (tcu::TestContext& testCtx)
898{
899	de::MovePtr<tcu::TestCaseGroup> renderingGroup(new tcu::TestCaseGroup(testCtx, "rendering"));
900
901	const struct
902	{
903		deUint32 colorAttachmentCount;
904		const char* name;
905	} colorAttachmentCountTests[] =
906	{
907		{ 0u,	"color_attachment_count_0",	},
908		{ 1u,	"color_attachment_count_1",	},
909		{ 4u,	"color_attachment_count_4",	},
910		{ 8u,	"color_attachment_count_8",	},
911	};
912
913	const struct
914	{
915		deUint32 extraAttachmentCount;
916		ExtraAttachments extraAttachment;
917		const char* name;
918	} extraAttachmentTests[] =
919	{
920		{ 0u,	NONE,		"none",							},
921		{ 1u,	BEFORE,		"extra_attachment_before_1",	},
922		{ 1u,	BETWEEN,	"extra_attachment_between_1",	},
923		{ 1u,	AFTER,		"extra_attachment_after_1",		},
924		{ 2u,	BEFORE,		"extra_attachment_before_2",	},
925		{ 2u,	BETWEEN,	"extra_attachment_between_2",	},
926		{ 2u,	AFTER,		"extra_attachment_after_2",		},
927	};
928
929	const struct
930	{
931		deUint32 extraFragmentOutputCount;
932		ExtraAttachments extraAttachment;
933		const char* name;
934	} extraOutputTests[] =
935	{
936		{ 0u,	NONE,		"none",						},
937		{ 1u,	BEFORE,		"extra_output_before_1",	},
938		{ 1u,	BETWEEN,	"extra_output_between_1",	},
939		{ 1u,	AFTER,		"extra_output_after_1",		},
940		{ 2u,	BEFORE,		"extra_output_before_2",	},
941		{ 2u,	BETWEEN,	"extra_output_between_2",	},
942		{ 2u,	AFTER,		"extra_output_after_2",		},
943	};
944
945	const vk::VkFormat		depthStencilFormats[] =
946	{
947		vk::VK_FORMAT_D16_UNORM,
948		vk::VK_FORMAT_X8_D24_UNORM_PACK32,
949		vk::VK_FORMAT_D32_SFLOAT,
950		vk::VK_FORMAT_D16_UNORM_S8_UINT,
951		vk::VK_FORMAT_D24_UNORM_S8_UINT,
952		vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
953	};
954
955	const struct
956	{
957		DummyRenderPass	dummyRenderPass;
958		const char* name;
959	} dummyRenderPassTests[] =
960	{
961		{ DUMMY_NONE,		"none",		},
962		{ DUMMY_DYNAMIC,	"dynamic",	},
963		{ DUMMY_STATIC,		"static",	},
964	};
965
966	for (const auto& colorAttachmentCountTest : colorAttachmentCountTests)
967	{
968		de::MovePtr<tcu::TestCaseGroup> colorAttachmentGroup(new tcu::TestCaseGroup(testCtx, colorAttachmentCountTest.name));
969		for (const auto& extraAttachment : extraAttachmentTests)
970		{
971			de::MovePtr<tcu::TestCaseGroup> extraAttachmentGroup(new tcu::TestCaseGroup(testCtx, extraAttachment.name));
972			for (const auto& extraOutput : extraOutputTests)
973			{
974				if (extraAttachment.extraAttachment != NONE && extraOutput.extraFragmentOutputCount != NONE)
975					continue;
976
977				de::MovePtr<tcu::TestCaseGroup> extraOutputGroup(new tcu::TestCaseGroup(testCtx, extraOutput.name));
978
979				for (const auto& dummyRenderPass : dummyRenderPassTests)
980				{
981					de::MovePtr<tcu::TestCaseGroup> dummyRenderPassGroup(new tcu::TestCaseGroup(testCtx, dummyRenderPass.name));
982					for (deUint32 m = 0; m < 2; ++m)
983					{
984						bool useRandomColorFormats = m == 0;
985						if (useRandomColorFormats && colorAttachmentCountTest.colorAttachmentCount < 2)
986							continue;
987						std::string randomColorFormatsName = useRandomColorFormats ? "random_color_formats" : "same_color_formats";
988						de::MovePtr<tcu::TestCaseGroup> randomColorFormatsGroup(new tcu::TestCaseGroup(testCtx, randomColorFormatsName.c_str()));
989						for (deUint32 k = 0; k < 2; ++k)
990						{
991							bool bindShadersBeforeBeginRendering = k == 0;
992							std::string bindName = bindShadersBeforeBeginRendering ? "before" : "after";
993							de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, bindName.c_str()));
994							for (deUint32 l = 0; l < 2; ++l)
995							{
996								bool writeGlFragDepth = l == 0;
997								std::string writeGlFragName = writeGlFragDepth ? "gl_frag_write" : "none";
998								de::MovePtr<tcu::TestCaseGroup> fragWriteGroup(new tcu::TestCaseGroup(testCtx, writeGlFragName.c_str()));
999								for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(colorFormats); ++i)
1000								{
1001									if (extraAttachment.extraAttachmentCount > colorAttachmentCountTest.colorAttachmentCount)
1002										continue;
1003
1004									if (!bindShadersBeforeBeginRendering && dummyRenderPass.dummyRenderPass != DUMMY_NONE)
1005										continue;
1006
1007									const auto colorFormat = colorFormats[i];
1008
1009									TestParams params;
1010									params.colorAttachmentCount = colorAttachmentCountTest.colorAttachmentCount;
1011									params.extraAttachmentCount = extraAttachment.extraAttachmentCount;
1012									params.extraAttachments = extraAttachment.extraAttachment;
1013									params.extraFragmentOutputCount = extraOutput.extraFragmentOutputCount;
1014									params.extraOutputs = extraOutput.extraAttachment;
1015									params.useDepthAttachment = false;
1016									params.colorFormat = colorFormat;
1017									params.depthFormat = vk::VK_FORMAT_UNDEFINED;
1018									params.bindShadersBeforeBeginRendering = bindShadersBeforeBeginRendering;
1019									params.dummyRenderPass = dummyRenderPass.dummyRenderPass;
1020									params.writeGlFragDepth = writeGlFragDepth;
1021									params.randomColorFormats = useRandomColorFormats;
1022
1023									std::string name = getFormatCaseName(colorFormat);
1024									fragWriteGroup->addChild(new ShaderObjectRenderingCase(testCtx, name, params));
1025
1026									if (writeGlFragDepth)
1027										continue;
1028
1029									for (deUint32 j = 0; j < DE_LENGTH_OF_ARRAY(depthStencilFormats); ++j)
1030									{
1031										const auto depthFormat = depthStencilFormats[j];
1032										params.useDepthAttachment = true;
1033										params.depthFormat = depthFormat;
1034
1035										std::string depthTestName = name + "_" + getFormatCaseName(depthFormat);
1036										fragWriteGroup->addChild(new ShaderObjectRenderingCase(testCtx, depthTestName, params));
1037									}
1038								}
1039								bindGroup->addChild(fragWriteGroup.release());
1040							}
1041							randomColorFormatsGroup->addChild(bindGroup.release());
1042						}
1043						dummyRenderPassGroup->addChild(randomColorFormatsGroup.release());
1044					}
1045					extraOutputGroup->addChild(dummyRenderPassGroup.release());
1046				}
1047				extraAttachmentGroup->addChild(extraOutputGroup.release());
1048			}
1049			colorAttachmentGroup->addChild(extraAttachmentGroup.release());
1050		}
1051		renderingGroup->addChild(colorAttachmentGroup.release());
1052	}
1053
1054	return renderingGroup.release();
1055}
1056
1057} // ShaderObject
1058} // vkt
1059