• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve Corporation.
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 Tests using depth/stencil images as descriptors.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktImageDepthStencilDescriptorTests.hpp"
26 
27 #include "vkBarrierUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkImageWithMemory.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkBufferWithMemory.hpp"
36 
37 #include "tcuMaybe.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43 
44 #include <iterator>
45 #include <vector>
46 #include <sstream>
47 #include <string>
48 
49 namespace vkt
50 {
51 namespace image
52 {
53 
54 namespace
55 {
56 
57 using namespace vk;
58 
getExtent()59 VkExtent3D getExtent ()
60 {
61 	return makeExtent3D(8u, 8u, 1u);
62 }
63 
getColorBufferFormat()64 VkFormat getColorBufferFormat ()
65 {
66 	return VK_FORMAT_R8G8B8A8_UNORM;
67 }
68 
getFloatStorageFormat()69 VkFormat getFloatStorageFormat ()
70 {
71 	return VK_FORMAT_R32_SFLOAT;
72 }
73 
getUintStorageFormat()74 VkFormat getUintStorageFormat ()
75 {
76 	return VK_FORMAT_R32_UINT;
77 }
78 
layoutExtension(VkImageLayout layout)79 tcu::Maybe<std::string> layoutExtension (VkImageLayout layout)
80 {
81 	std::string extension;
82 
83 	switch (layout)
84 	{
85 	case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
86 	case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
87 		extension = "VK_KHR_maintenance2";
88 		break;
89 	case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL:
90 	case VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL:
91 		// Note: we will not be using separate depth/stencil layouts. There's a separate group of tests for that.
92 		extension = "VK_KHR_separate_depth_stencil_layouts";
93 		break;
94 	default:
95 		DE_ASSERT(false);
96 		break;
97 	}
98 
99 	if (!extension.empty())
100 		return tcu::just(extension);
101 	return tcu::Nothing;
102 }
103 
104 // Types of access for an image aspect.
105 enum class AspectAccess
106 {
107 	NONE	= 0,
108 	RO		= 1,	// Different subtypes, see below.
109 	RW		= 2,	// This always means a normal read/write depth/stencil attachment (NOT a storage image).
110 };
111 
operator <<(std::ostream & stream,AspectAccess access)112 std::ostream& operator<< (std::ostream& stream, AspectAccess access)
113 {
114 	if		(access == AspectAccess::NONE)	stream << "none";
115 	else if	(access == AspectAccess::RO)	stream << "ro";
116 	else if	(access == AspectAccess::RW)	stream << "rw";
117 	else									DE_ASSERT(false);
118 
119 	return stream;
120 }
121 
122 // Types of read-only accesses.
123 enum class ReadOnlyAccess
124 {
125 	DS_ATTACHMENT		= 0,	// Depth/stencil attachment but read-only (writes not enabled).
126 	INPUT_ATTACHMENT	= 1,	// Input attachment in the set.
127 	SAMPLED				= 2,	// Sampled image.
128 };
129 
operator <<(std::ostream & stream,ReadOnlyAccess access)130 std::ostream& operator<< (std::ostream& stream, ReadOnlyAccess access)
131 {
132 	if		(access == ReadOnlyAccess::DS_ATTACHMENT)		stream << "att";
133 	else if	(access == ReadOnlyAccess::INPUT_ATTACHMENT)	stream << "ia";
134 	else if	(access == ReadOnlyAccess::SAMPLED)				stream << "sampled";
135 	else													DE_ASSERT(false);
136 
137 	return stream;
138 }
139 
140 // A given layout gives different accesses to each aspect.
getLegalAccess(VkImageLayout layout,VkImageAspectFlagBits aspect)141 AspectAccess getLegalAccess (VkImageLayout layout, VkImageAspectFlagBits aspect)
142 {
143 	DE_ASSERT(aspect == VK_IMAGE_ASPECT_DEPTH_BIT || aspect == VK_IMAGE_ASPECT_STENCIL_BIT);
144 
145 	if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL)
146 		return ((aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? AspectAccess::RW : AspectAccess::RO);
147 	else if (layout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL)
148 		return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? AspectAccess::RW : AspectAccess::RO);
149 	else if (layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL)
150 		return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? AspectAccess::RO : AspectAccess::NONE);
151 	else if (layout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)
152 		return ((aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? AspectAccess::RO : AspectAccess::NONE);
153 
154 	DE_ASSERT(false);
155 	return AspectAccess::NONE; // Unreachable.
156 }
157 
158 using ROAccessVec = std::vector<ReadOnlyAccess>;
159 
operator <<(std::ostream & stream,const ROAccessVec & vec)160 std::ostream& operator<< (std::ostream& stream, const ROAccessVec& vec)
161 {
162 	for (size_t i = 0u; i < vec.size(); ++i)
163 		stream << ((i > 0u) ? "_" : "") << vec[i];
164 	return stream;
165 }
166 
167 // We cannot access depth/stencil images both as a depth/stencil attachment and an input attachment at the same time if they have
168 // both aspects, because input attachments can only have one aspect.
incompatibleInputAttachmentAccess(AspectAccess depthAccess,const ROAccessVec * depthROAccesses,AspectAccess stencilAccess,const ROAccessVec * stencilROAccesses)169 bool incompatibleInputAttachmentAccess (AspectAccess depthAccess, const ROAccessVec* depthROAccesses, AspectAccess stencilAccess, const ROAccessVec* stencilROAccesses)
170 {
171 	const bool depthAsDSAttachment		= (depthAccess == AspectAccess::RW || (depthAccess == AspectAccess::RO && de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
172 	const bool stencilAsDSAttachment	= (stencilAccess == AspectAccess::RW || (stencilAccess == AspectAccess::RO && de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
173 	const bool depthAsInputAttachment	= (depthAccess == AspectAccess::RO && de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
174 	const bool stencilAsInputAttachment	= (stencilAccess == AspectAccess::RO && de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
175 
176 	return ((depthAsDSAttachment && stencilAsInputAttachment) || (stencilAsDSAttachment && depthAsInputAttachment));
177 }
178 
getReadOnlyUsageFlags(const ROAccessVec & readOnlyAccesses)179 VkImageUsageFlags getReadOnlyUsageFlags (const ROAccessVec& readOnlyAccesses)
180 {
181 	VkImageUsageFlags usageFlags = 0u;
182 
183 	for (const auto& access : readOnlyAccesses)
184 	{
185 		if (access == ReadOnlyAccess::DS_ATTACHMENT)
186 			usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
187 		else if (access == ReadOnlyAccess::INPUT_ATTACHMENT)
188 			usageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
189 		else if (access == ReadOnlyAccess::SAMPLED)
190 			usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
191 		else
192 			DE_ASSERT(false);
193 	}
194 
195 	return usageFlags;
196 }
197 
198 // Resources needed for an aspect that will be used as a descriptor in shaders (sampled or input attachment).
199 struct InputOutputDescriptor
200 {
201 	uint32_t				binding;
202 	tcu::Maybe<uint32_t>	inputAttachmentIndex;
203 	VkImageAspectFlagBits	aspect;
204 };
205 
206 using IODescVec = std::vector<InputOutputDescriptor>;
207 
208 // Test parameters.
209 struct TestParams
210 {
211 	VkFormat				format;				// Image format.
212 	VkImageLayout			layout;				// Layout being tested.
213 	AspectAccess			depthAccess;		// Type of access that will be used for depth (must be legal).
214 	AspectAccess			stencilAccess;		// Type of access that will be used for stencil (must be legal).
215 
216 	tcu::Maybe<ROAccessVec>	depthROAccesses;	// Types of read-only accesses for depth (used when depthAccess is RO).
217 	tcu::Maybe<ROAccessVec>	stencilROAccesses;	// Types of read-only accesses for stencil (used when stencilAccess is RO).
218 
219 	VkImageUsageFlags		getUsageFlags () const;
220 
221 	// Get a list of descriptors needed according to the given test parameters.
222 	IODescVec				getDescriptors () const;
223 
224 	// Does this case need a depth/stencil attachment?
225 	bool					dsAttachmentNeeded () const;
226 
227 	// Does this case use the depth aspect as an input attachment?
228 	bool					depthAsInputAttachment () const;
229 
230 	// Does this case use the stencil aspect as an input attachment?
231 	bool					stencilAsInputAttachment () const;
232 
233 	// Does this case need an input attachment?
234 	bool					inputAttachmentNeeded () const;
235 
236 	// Does this case need a depth/stencil attachment as a depth buffer?
237 	bool					depthBufferNeeded () const;
238 
239 	// Does this case need the pipeline depth test enabled?
240 	bool					needsDepthTest () const;
241 
242 	// Does this case need the stencil test enabled?
243 	bool					needsStencilTest () const;
244 };
245 
getUsageFlags() const246 VkImageUsageFlags TestParams::getUsageFlags () const
247 {
248 	VkImageUsageFlags usageFlags = (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
249 
250 	if (depthAccess == AspectAccess::RW || stencilAccess == AspectAccess::RW)
251 		usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
252 
253 	if (depthAccess == AspectAccess::RO)
254 	{
255 		DE_ASSERT(static_cast<bool>(depthROAccesses));
256 		usageFlags |= getReadOnlyUsageFlags(*depthROAccesses);
257 	}
258 
259 	if (stencilAccess == AspectAccess::RO)
260 	{
261 		DE_ASSERT(static_cast<bool>(stencilROAccesses));
262 		usageFlags |= getReadOnlyUsageFlags(*stencilROAccesses);
263 	}
264 
265 	return usageFlags;
266 }
267 
addDescriptors(IODescVec & descriptors,uint32_t & inputAttachmentCount,const ROAccessVec & accesses,VkImageAspectFlagBits aspect)268 void addDescriptors (IODescVec& descriptors, uint32_t& inputAttachmentCount, const ROAccessVec& accesses, VkImageAspectFlagBits aspect)
269 {
270 	for (const auto& access : accesses)
271 	{
272 		// Get a new binding number and a new input attachment index if needed, then append the new descriptor to the list if
273 		// appropriate.
274 
275 		InputOutputDescriptor descriptor =
276 		{
277 			static_cast<uint32_t>(descriptors.size()),	//	uint32_t				binding;
278 			tcu::Nothing,								//	tcu::Maybe<uint32_t>	inputAttachmentIndex;
279 			aspect,										//	VkImageAspectFlagBits	aspect;
280 		};
281 
282 		if (access == ReadOnlyAccess::INPUT_ATTACHMENT)
283 			descriptor.inputAttachmentIndex = tcu::just(inputAttachmentCount++);
284 
285 		if (access == ReadOnlyAccess::INPUT_ATTACHMENT || access == ReadOnlyAccess::SAMPLED)
286 			descriptors.push_back(descriptor);
287 	}
288 }
289 
getDescriptors() const290 IODescVec TestParams::getDescriptors () const
291 {
292 	IODescVec descriptors;
293 	uint32_t inputAttachmentCount = 0u;
294 
295 	if (static_cast<bool>(depthROAccesses))
296 		addDescriptors(descriptors, inputAttachmentCount, *depthROAccesses, VK_IMAGE_ASPECT_DEPTH_BIT);
297 
298 	if (static_cast<bool>(stencilROAccesses))
299 		addDescriptors(descriptors, inputAttachmentCount, *stencilROAccesses, VK_IMAGE_ASPECT_STENCIL_BIT);
300 
301 	return descriptors;
302 }
303 
dsAttachmentNeeded() const304 bool TestParams::dsAttachmentNeeded () const
305 {
306 	// The depth/stencil attachment is needed if the image is going to be used as a depth/stencil attachment or an input attachment.
307 	return (inputAttachmentNeeded() || depthBufferNeeded());
308 }
309 
depthAsInputAttachment() const310 bool TestParams::depthAsInputAttachment () const
311 {
312 	return (depthAccess == AspectAccess::RO && de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
313 }
314 
stencilAsInputAttachment() const315 bool TestParams::stencilAsInputAttachment () const
316 {
317 	return (stencilAccess == AspectAccess::RO && de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::INPUT_ATTACHMENT));
318 }
319 
inputAttachmentNeeded() const320 bool TestParams::inputAttachmentNeeded () const
321 {
322 	// An input attachment is needed if any of the depth or stencil aspects include a read-only access as an input attachment.
323 	return (depthAsInputAttachment() || stencilAsInputAttachment());
324 }
325 
depthBufferNeeded() const326 bool TestParams::depthBufferNeeded () const
327 {
328 	// The depth buffer is needed if any of the depth or stencil aspects include a read-write or read-only DS access.
329 	return (needsDepthTest() || needsStencilTest());
330 }
331 
needsDepthTest() const332 bool TestParams::needsDepthTest () const
333 {
334 	// The depth test is needed if the depth aspect includes a read-write or read-only DS access.
335 	return (depthAccess == AspectAccess::RW || (depthAccess == AspectAccess::RO && de::contains(begin(*depthROAccesses), end(*depthROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
336 }
337 
needsStencilTest() const338 bool TestParams::needsStencilTest () const
339 {
340 	// The stencil test is needed if the stencil aspect includes a read-write or read-only DS access.
341 	return (stencilAccess == AspectAccess::RW || (stencilAccess == AspectAccess::RO && de::contains(begin(*stencilROAccesses), end(*stencilROAccesses), ReadOnlyAccess::DS_ATTACHMENT)));
342 }
343 
344 class DepthStencilDescriptorCase : public vkt::TestCase
345 {
346 public:
347 					DepthStencilDescriptorCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
~DepthStencilDescriptorCase(void)348 	virtual			~DepthStencilDescriptorCase		(void) {}
349 
350 	void			checkSupport	(Context& context) const override;
351 	TestInstance*	createInstance	(Context& context) const override;
352 	void			initPrograms	(vk::SourceCollections& programCollection) const override;
353 
354 protected:
355 	TestParams		m_params;
356 };
357 
358 class DepthStencilDescriptorInstance : public vkt::TestInstance
359 {
360 public:
361 					DepthStencilDescriptorInstance	(Context& context, const TestParams& params);
~DepthStencilDescriptorInstance(void)362 	virtual			~DepthStencilDescriptorInstance	(void) {}
363 
364 	tcu::TestStatus	iterate() override;
365 
366 protected:
367 	// Must match the shaders.
368 	struct PushConstantData
369 	{
370 		float colorR;
371 		float colorG;
372 		float colorB;
373 		float colorA;
374 		float depth;
375 
PushConstantDatavkt::image::__anon87891cc00111::DepthStencilDescriptorInstance::PushConstantData376 		PushConstantData ()
377 			: colorR	(0.0f)
378 			, colorG	(0.0f)
379 			, colorB	(0.0f)
380 			, colorA	(0.0f)
381 			, depth		(0.0f)
382 		{}
383 
PushConstantDatavkt::image::__anon87891cc00111::DepthStencilDescriptorInstance::PushConstantData384 		PushConstantData (const tcu::Vec4& color, float depth_)
385 			: colorR	(color.x())
386 			, colorG	(color.y())
387 			, colorB	(color.z())
388 			, colorA	(color.w())
389 			, depth		(depth_)
390 		{}
391 	};
392 
393 	TestParams		m_params;
394 };
395 
DepthStencilDescriptorCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)396 DepthStencilDescriptorCase::DepthStencilDescriptorCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
397 	: vkt::TestCase	(testCtx, name, description)
398 	, m_params		(params)
399 {}
400 
checkSupport(Context & context) const401 void DepthStencilDescriptorCase::checkSupport (Context& context) const
402 {
403 	context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
404 
405 	const auto requiredExtension = layoutExtension(m_params.layout);
406 	if (requiredExtension)
407 		context.requireDeviceFunctionality(*requiredExtension);
408 
409 	// Check format support.
410 	const auto&		vki		= context.getInstanceInterface();
411 	const auto		physDev	= context.getPhysicalDevice();
412 	const auto		imgType	= VK_IMAGE_TYPE_2D;
413 	const auto		tiling	= VK_IMAGE_TILING_OPTIMAL;
414 	const auto		usage	= m_params.getUsageFlags();
415 
416 	VkImageFormatProperties formatProperties;
417 	const auto res = vki.getPhysicalDeviceImageFormatProperties(physDev, m_params.format, imgType, tiling, usage, 0u, &formatProperties);
418 	if (res == VK_ERROR_FORMAT_NOT_SUPPORTED)
419 		TCU_THROW(NotSupportedError, "Format does not support required properties");
420 	else if (res != VK_SUCCESS)
421 		TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned " + de::toString(res));
422 }
423 
createInstance(Context & context) const424 TestInstance* DepthStencilDescriptorCase::createInstance (Context& context) const
425 {
426 	return new DepthStencilDescriptorInstance(context, m_params);
427 }
428 
initPrograms(vk::SourceCollections & programCollection) const429 void DepthStencilDescriptorCase::initPrograms (vk::SourceCollections& programCollection) const
430 {
431 	std::ostringstream vert;
432 	vert
433 		<< "#version 450\n"
434 		<< "\n"
435 		<< "layout(push_constant, std430) uniform PushConstantBlock {\n"
436 		<< "    float colorR;\n"
437 		<< "    float colorG;\n"
438 		<< "    float colorB;\n"
439 		<< "    float colorA;\n"
440 		<< "    float depth;\n"
441 		<< "} pc;\n"
442 		<< "\n"
443 		<< "vec2 vertexPositions[3] = vec2[](\n"
444 		<< "    vec2(-1.0, -1.0),\n"
445 		<< "    vec2(-1.0,  3.0),\n"
446 		<< "    vec2( 3.0, -1.0));\n"
447 		<< "\n"
448 		<< "void main () {\n"
449 		<< "    gl_Position = vec4(vertexPositions[gl_VertexIndex], pc.depth, 1.0);\n"
450 		<< "}\n"
451 		;
452 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
453 
454 	// When any of the image aspects is going to be used as an input attachment or sampled image, we need an input descriptor and an
455 	// output descriptor to verify reading from it.
456 	std::ostringstream	descriptorsDecl;
457 	std::ostringstream	descriptorsSideEffects;
458 	const auto			descriptors				= m_params.getDescriptors();
459 
460 	// Samplers set (set number 2).
461 	descriptorsDecl
462 		<< "layout (set=2, binding=0) uniform sampler globalSampler;\n"		// Sampler with float border color (depth).
463 		<< "layout (set=2, binding=1) uniform sampler uglobalSampler;\n"	// Sampler with int border color (stencil).
464 		;
465 
466 	for (const auto& descriptor : descriptors)
467 	{
468 		const auto			prefix = ((descriptor.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? "u" : "");
469 		const auto			suffix = ((descriptor.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) ? "ui" : "f");
470 		std::ostringstream	loadOp;
471 
472 		// Input descriptor declaration.
473 		if (static_cast<bool>(descriptor.inputAttachmentIndex))
474 		{
475 			const auto& iaIndex = *descriptor.inputAttachmentIndex;
476 			descriptorsDecl << "layout (input_attachment_index=" << iaIndex << ", set=0, binding=" << descriptor.binding << ") uniform " << prefix << "subpassInput attachment" << descriptor.binding << ";\n";
477 			loadOp << "subpassLoad(attachment" << descriptor.binding << ")";
478 		}
479 		else
480 		{
481 			descriptorsDecl << "layout (set=0, binding=" << descriptor.binding << ") uniform " << prefix << "texture2D sampledImage" << descriptor.binding << ";\n";
482 			loadOp << "texture(" << prefix << "sampler2D(sampledImage" << descriptor.binding << ", " << prefix << "globalSampler), gl_FragCoord.xy)"; // This needs a sampler with unnormalizedCoordinates == VK_TRUE.
483 		}
484 
485 		// Output descriptor declaration (output descriptors in set 1).
486 		descriptorsDecl << "layout (r32" << suffix << ", set=1, binding=" << descriptor.binding << ") uniform " << prefix << "image2D storage" << descriptor.binding << ";\n";
487 
488 		// The corresponding side effect.
489 		descriptorsSideEffects << "    imageStore(storage" << descriptor.binding << ", ivec2(gl_FragCoord.xy), " << loadOp.str() << ");\n";
490 	}
491 
492 	std::ostringstream frag;
493 	frag
494 		<< "#version 450\n"
495 		<< "\n"
496 		<< "layout(location=0) out vec4 outColor;\n"
497 		<< "layout(push_constant, std430) uniform PushConstantBlock {\n"
498 		<< "    float colorR;\n"
499 		<< "    float colorG;\n"
500 		<< "    float colorB;\n"
501 		<< "    float colorA;\n"
502 		<< "    float depth;\n"
503 		<< "} pc;\n"
504 		<< "\n"
505 		<< descriptorsDecl.str()
506 		<< "\n"
507 		<< "void main () {\n"
508 		<< descriptorsSideEffects.str()
509 		<< "    outColor = vec4(pc.colorR, pc.colorG, pc.colorB, pc.colorA);\n"
510 		<< "}\n"
511 		;
512 
513 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
514 }
515 
DepthStencilDescriptorInstance(Context & context,const TestParams & params)516 DepthStencilDescriptorInstance::DepthStencilDescriptorInstance (Context& context, const TestParams& params)
517 	: vkt::TestInstance	(context)
518 	, m_params			(params)
519 {}
520 
getAspectStorageFormat(VkImageAspectFlagBits aspect)521 VkFormat getAspectStorageFormat (VkImageAspectFlagBits aspect)
522 {
523 	return ((aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? getFloatStorageFormat() : getUintStorageFormat());
524 }
525 
getCopyBufferSize(const tcu::TextureFormat & format,const VkExtent3D & extent)526 VkDeviceSize getCopyBufferSize (const tcu::TextureFormat& format, const VkExtent3D& extent)
527 {
528 	return static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(format)) * extent.width * extent.height * extent.depth);
529 }
530 
iterate()531 tcu::TestStatus	DepthStencilDescriptorInstance::iterate ()
532 {
533 	const auto&		vkd				= m_context.getDeviceInterface();
534 	const auto		device			= m_context.getDevice();
535 	auto&			alloc			= m_context.getDefaultAllocator();
536 	const auto		qIndex			= m_context.getUniversalQueueFamilyIndex();
537 	const auto		queue			= m_context.getUniversalQueue();
538 	const auto		extent			= getExtent();
539 	const auto		usage			= m_params.getUsageFlags();
540 	const auto		colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
541 	const auto		colorFormat		= getColorBufferFormat();
542 	const auto		tcuColorFormat	= mapVkFormat(colorFormat);
543 	const auto		storageUsage	= (VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
544 	const auto		stageFlags		= VK_SHADER_STAGE_FRAGMENT_BIT;
545 	const auto		tcuFormat		= mapVkFormat(m_params.format);
546 	const auto		hasDepth		= tcu::hasDepthComponent(tcuFormat.order);
547 	const auto		hasStencil		= tcu::hasStencilComponent(tcuFormat.order);
548 	const auto		colorSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
549 	const auto		outputImgLayout	= VK_IMAGE_LAYOUT_GENERAL;
550 	const auto		colorLayout		= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
551 
552 	// Copy formats.
553 	const auto		tcuDepthFormat		= (hasDepth ?	getDepthCopyFormat(m_params.format)		: tcu::TextureFormat());
554 	const auto		tcuStencilFormat	= (hasStencil ?	getStencilCopyFormat(m_params.format)	: tcu::TextureFormat());
555 
556 	// These must match the depth test configuration when enabled.
557 	const float		depthClearValue	= 0.5f;
558 	const float		depthFailValue	= 1.0f;
559 	const float		depthPassValue	= 0.0f;
560 
561 	// These must match the stencil test configuration when enabled.
562 	const uint32_t	stencilClearVal	= 100u;
563 	const uint32_t	stencilFailVal	= 200u;
564 	const uint32_t	stencilPassVal	= 10u;
565 
566 	// For the color buffer.
567 	const tcu::Vec4	colorClearVal	(0.0f, 0.0f, 0.0f, 1.0f);
568 	const tcu::Vec4	colorFailVal	(1.0f, 0.0f, 0.0f, 1.0f);
569 	const tcu::Vec4	colorPassVal	(0.0f, 1.0f, 0.0f, 1.0f);
570 
571 	// Will the test update the depth/stencil buffer?
572 	const auto stencilWrites	= (m_params.stencilAccess == AspectAccess::RW);
573 	const auto depthWrites		= (m_params.depthAccess == AspectAccess::RW);
574 
575 	// Create color attachment.
576 	const VkImageCreateInfo colorBufferInfo =
577 	{
578 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
579 		nullptr,								//	const void*				pNext;
580 		0u,										//	VkImageCreateFlags		flags;
581 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
582 		colorFormat,							//	VkFormat				format;
583 		extent,									//	VkExtent3D				extent;
584 		1u,										//	uint32_t				mipLevels;
585 		1u,										//	uint32_t				arrayLayers;
586 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
587 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
588 		colorUsage,								//	VkImageUsageFlags		usage;
589 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
590 		0u,										//	uint32_t				queueFamilyIndexCount;
591 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
592 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
593 	};
594 	ImageWithMemory	colorBuffer	(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
595 	const auto		colorView	= makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
596 
597 	// Create depth/stencil image.
598 	const VkImageCreateInfo dsImageInfo =
599 	{
600 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
601 		nullptr,								//	const void*				pNext;
602 		0u,										//	VkImageCreateFlags		flags;
603 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
604 		m_params.format,						//	VkFormat				format;
605 		extent,									//	VkExtent3D				extent;
606 		1u,										//	uint32_t				mipLevels;
607 		1u,										//	uint32_t				arrayLayers;
608 		VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
609 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
610 		usage,									//	VkImageUsageFlags		usage;
611 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
612 		0u,										//	uint32_t				queueFamilyIndexCount;
613 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
614 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
615 	};
616 	ImageWithMemory dsImage(vkd, device, alloc, dsImageInfo, MemoryRequirement::Any);
617 	const auto depthStencilSRR	= makeImageSubresourceRange(getImageAspectFlags(tcuFormat), 0u, 1u, 0u, 1u);
618 	const auto depthSRR			= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
619 	const auto stencilSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
620 	const auto dsImageView		= makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, depthStencilSRR);
621 
622 	Move<VkImageView> depthOnlyView;
623 	Move<VkImageView> stencilOnlyView;
624 
625 	if (hasDepth)
626 		depthOnlyView = makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, depthSRR);
627 
628 	if (hasStencil)
629 		stencilOnlyView = makeImageView(vkd, device, dsImage.get(), VK_IMAGE_VIEW_TYPE_2D, m_params.format, stencilSRR);
630 
631 	// Get expected descriptors and create output images for them.
632 	const auto descriptors = m_params.getDescriptors();
633 
634 	std::vector<de::MovePtr<ImageWithMemory>>	outputImages;
635 	std::vector<Move<VkImageView>>				outputImageViews;
636 
637 	outputImages.reserve(descriptors.size());
638 	outputImageViews.reserve(descriptors.size());
639 
640 	for (const auto& desc : descriptors)
641 	{
642 		// Floating point images to copy the depth aspect and unsigned int images to copy the stencil aspect.
643 		const auto imageFormat = getAspectStorageFormat(desc.aspect);
644 
645 		const VkImageCreateInfo createInfo =
646 		{
647 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
648 			nullptr,								//	const void*				pNext;
649 			0u,										//	VkImageCreateFlags		flags;
650 			VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
651 			imageFormat,							//	VkFormat				format;
652 			extent,									//	VkExtent3D				extent;
653 			1u,										//	uint32_t				mipLevels;
654 			1u,										//	uint32_t				arrayLayers;
655 			VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
656 			VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
657 			storageUsage,							//	VkImageUsageFlags		usage;
658 			VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
659 			0u,										//	uint32_t				queueFamilyIndexCount;
660 			nullptr,								//	const uint32_t*			pQueueFamilyIndices;
661 			VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
662 		};
663 
664 		outputImages.push_back(de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, alloc, createInfo, MemoryRequirement::Any)));
665 		outputImageViews.push_back(makeImageView(vkd, device, outputImages.back()->get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR));
666 	}
667 
668 	// Create samplers.
669 	Move<VkSampler> samplerFloat;
670 	Move<VkSampler> samplerInt;
671 	{
672 		VkSamplerCreateInfo samplerCreateInfo =
673 		{
674 			VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,	//	VkStructureType			sType;
675 			nullptr,								//	const void*				pNext;
676 			0u,										//	VkSamplerCreateFlags	flags;
677 			VK_FILTER_NEAREST,						//	VkFilter				magFilter;
678 			VK_FILTER_NEAREST,						//	VkFilter				minFilter;
679 			VK_SAMPLER_MIPMAP_MODE_NEAREST,			//	VkSamplerMipmapMode		mipmapMode;
680 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,	//	VkSamplerAddressMode	addressModeU;
681 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,	//	VkSamplerAddressMode	addressModeV;
682 			VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,	//	VkSamplerAddressMode	addressModeW;
683 			0.0f,									//	float					mipLodBias;
684 			VK_FALSE,								//	VkBool32				anisotropyEnable;
685 			0.0f,									//	float					maxAnisotropy;
686 			VK_FALSE,								//	VkBool32				compareEnable;
687 			VK_COMPARE_OP_LAST,						//	VkCompareOp				compareOp;
688 			0.0f,									//	float					minLod;
689 			0.0f,									//	float					maxLod;
690 			VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,		//	VkBorderColor			borderColor;
691 			VK_TRUE,								//	VkBool32				unnormalizedCoordinates;
692 		};
693 		// Note the samplers are created with unnormalizedCoordinates as per how they are used in shader code.
694 		samplerFloat = createSampler(vkd, device, &samplerCreateInfo);
695 
696 		samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
697 		samplerInt = createSampler(vkd, device, &samplerCreateInfo);
698 	}
699 
700 	// Create input and output descriptor set layouts.
701 	Move<VkDescriptorSetLayout> inputSetLayout;
702 	Move<VkDescriptorSetLayout> outputSetLayout;
703 	Move<VkDescriptorSetLayout> samplerSetLayout;
704 
705 	{
706 		DescriptorSetLayoutBuilder inputLayoutBuilder;
707 		for (const auto& desc : descriptors)
708 		{
709 			if (static_cast<bool>(desc.inputAttachmentIndex))
710 				inputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, stageFlags);
711 			else
712 				inputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags);
713 		}
714 		inputSetLayout = inputLayoutBuilder.build(vkd, device);
715 	}
716 	{
717 		DescriptorSetLayoutBuilder outputLayoutBuilder;
718 		for (size_t i = 0; i < descriptors.size(); ++i)
719 			outputLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, stageFlags);
720 		outputSetLayout = outputLayoutBuilder.build(vkd, device);
721 	}
722 	{
723 		DescriptorSetLayoutBuilder samplerLayoutBuilder;
724 		samplerLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, stageFlags);
725 		samplerLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, stageFlags);
726 		samplerSetLayout = samplerLayoutBuilder.build(vkd, device);
727 	}
728 
729 	const std::vector<VkDescriptorSetLayout> setLayouts = { inputSetLayout.get(), outputSetLayout.get(), samplerSetLayout.get() };
730 
731 	// Descriptor pool and descriptor sets.
732 	Move<VkDescriptorPool>	descriptorPool;
733 	Move<VkDescriptorSet>	inputSet;
734 	Move<VkDescriptorSet>	outputSet;
735 	Move<VkDescriptorSet>	samplerSet;
736 	{
737 		DescriptorPoolBuilder poolBuilder;
738 
739 		// Input descriptors.
740 		for (const auto& desc : descriptors)
741 		{
742 			if (static_cast<bool>(desc.inputAttachmentIndex))
743 				poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
744 			else
745 				poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
746 		}
747 
748 		// Output descriptors.
749 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, static_cast<uint32_t>(descriptors.size()));
750 
751 		// Global samplers.
752 		poolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 2u);
753 
754 		descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, static_cast<uint32_t>(setLayouts.size()));
755 	}
756 
757 	inputSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), inputSetLayout.get());
758 	outputSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), outputSetLayout.get());
759 	samplerSet	= makeDescriptorSet(vkd, device, descriptorPool.get(), samplerSetLayout.get());
760 
761 	const std::vector<VkDescriptorSet> descriptorSets = { inputSet.get(), outputSet.get(), samplerSet.get() };
762 
763 	// Update descriptor sets.
764 	{
765 		DescriptorSetUpdateBuilder inputUpdateBuilder;
766 		DescriptorSetUpdateBuilder outputUpdateBuilder;
767 		DescriptorSetUpdateBuilder samplerUpdateBuilder;
768 
769 		std::vector<VkDescriptorImageInfo> inputImgInfos;
770 		std::vector<VkDescriptorImageInfo> outputImgInfos;
771 		std::vector<VkDescriptorImageInfo> samplerImgInfos;
772 
773 		// Make sure addresses are stable (pushing elements back while taking their addresses).
774 		inputImgInfos.reserve(descriptors.size());
775 		outputImgInfos.reserve(descriptors.size());
776 		samplerImgInfos.reserve(2u);
777 
778 		for (size_t descriptorIdx = 0u; descriptorIdx < descriptors.size(); ++descriptorIdx)
779 		{
780 			const auto& desc		= descriptors[descriptorIdx];
781 			const auto	isIA		= static_cast<bool>(desc.inputAttachmentIndex);
782 			const auto	location	= DescriptorSetUpdateBuilder::Location::binding(desc.binding);
783 
784 			// Input descriptors.
785 			const auto inType	= (isIA ? VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
786 			const auto view		= ((desc.aspect == VK_IMAGE_ASPECT_DEPTH_BIT) ? depthOnlyView.get() : stencilOnlyView.get());
787 			inputImgInfos.push_back(makeDescriptorImageInfo(DE_NULL, view, m_params.layout));
788 			inputUpdateBuilder.writeSingle(inputSet.get(), location, inType, &inputImgInfos.back());
789 
790 			// Output descriptors.
791 			outputImgInfos.push_back(makeDescriptorImageInfo(DE_NULL, outputImageViews[descriptorIdx].get(), outputImgLayout));
792 			outputUpdateBuilder.writeSingle(outputSet.get(), location, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &outputImgInfos.back());
793 		}
794 
795 		inputUpdateBuilder.update(vkd, device);
796 		outputUpdateBuilder.update(vkd, device);
797 
798 		// Samplers.
799 		samplerImgInfos.push_back(makeDescriptorImageInfo(samplerFloat.get(), DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED));
800 		samplerUpdateBuilder.writeSingle(samplerSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_SAMPLER, &samplerImgInfos.back());
801 
802 		samplerImgInfos.push_back(makeDescriptorImageInfo(samplerInt.get(), DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED));
803 		samplerUpdateBuilder.writeSingle(samplerSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_SAMPLER, &samplerImgInfos.back());
804 
805 		samplerUpdateBuilder.update(vkd, device);
806 	}
807 
808 	PushConstantData	pcData;
809 	const auto			pcStages	= (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
810 	const auto			pcSize		= static_cast<uint32_t>(sizeof(pcData));
811 	const auto			pcRange		= makePushConstantRange(pcStages, 0u, pcSize);
812 
813 	// Pipeline layout.
814 	const auto pipelineLayout = makePipelineLayout(vkd, device, static_cast<uint32_t>(setLayouts.size()), de::dataOrNull(setLayouts), 1u, &pcRange);
815 
816 	// Render pass.
817 	Move<VkRenderPass> renderPass;
818 
819 	{
820 		std::vector<VkAttachmentDescription2>	attachmentDescriptions;
821 		std::vector<VkAttachmentReference2>		attachmentReferences;
822 
823 		const VkAttachmentDescription2 colorAttachmentDesc =
824 		{
825 			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,		//	VkStructureType					sType;
826 			nullptr,										//	const void*						pNext;
827 			0u,												//	VkAttachmentDescriptionFlags	flags;
828 			colorFormat,									//	VkFormat						format;
829 			VK_SAMPLE_COUNT_1_BIT,							//	VkSampleCountFlagBits			samples;
830 			VK_ATTACHMENT_LOAD_OP_LOAD,						//	VkAttachmentLoadOp				loadOp;
831 			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
832 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
833 			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
834 			colorLayout,									//	VkImageLayout					initialLayout;
835 			colorLayout,									//	VkImageLayout					finalLayout;
836 		};
837 		attachmentDescriptions.push_back(colorAttachmentDesc);
838 
839 		const VkAttachmentReference2 colorAttachmentRef =
840 		{
841 			VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,	//	VkStructureType		sType;
842 			nullptr,									//	const void*			pNext;
843 			0u,											//	uint32_t			attachment;
844 			colorLayout,								//	VkImageLayout		layout;
845 			VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
846 		};
847 		attachmentReferences.push_back(colorAttachmentRef);
848 
849 		const auto needsIA			= m_params.inputAttachmentNeeded();
850 		const auto needsDepthBuffer	= m_params.depthBufferNeeded();
851 		DE_ASSERT(!(needsIA && needsDepthBuffer));
852 
853 		if (m_params.dsAttachmentNeeded())
854 		{
855 			const VkAttachmentDescription2 dsAttachmentDesc =
856 			{
857 				VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,
858 				nullptr,
859 				0u,
860 				m_params.format,
861 				VK_SAMPLE_COUNT_1_BIT,
862 				(hasDepth						? VK_ATTACHMENT_LOAD_OP_LOAD	: VK_ATTACHMENT_LOAD_OP_DONT_CARE),
863 				((hasDepth && depthWrites)		? VK_ATTACHMENT_STORE_OP_STORE	: VK_ATTACHMENT_STORE_OP_DONT_CARE),
864 				(hasStencil						? VK_ATTACHMENT_LOAD_OP_LOAD	: VK_ATTACHMENT_LOAD_OP_DONT_CARE),
865 				((hasStencil && stencilWrites)	? VK_ATTACHMENT_STORE_OP_STORE	: VK_ATTACHMENT_STORE_OP_DONT_CARE),
866 				m_params.layout,
867 				m_params.layout,
868 			};
869 			attachmentDescriptions.push_back(dsAttachmentDesc);
870 
871 			const VkAttachmentReference2 dsAttachmentRef =
872 			{
873 				VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,	//	VkStructureType		sType;
874 				nullptr,									//	const void*			pNext;
875 				1u,											//	uint32_t			attachment;
876 				m_params.layout,							//	VkImageLayout		layout;
877 															//	VkImageAspectFlags	aspectMask;
878 				(	(m_params.depthAsInputAttachment()		? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT)	: 0u)
879 				 |	(m_params.stencilAsInputAttachment()	? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_STENCIL_BIT)	: 0u)),
880 			};
881 
882 			attachmentReferences.push_back(dsAttachmentRef);
883 		}
884 
885 		const VkSubpassDescription2 subpassDesc =
886 		{
887 			VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,					//	VkStructureType					sType;
888 			nullptr,													//	const void*						pNext;
889 			0u,															//	VkSubpassDescriptionFlags		flags;
890 			VK_PIPELINE_BIND_POINT_GRAPHICS,							//	VkPipelineBindPoint				pipelineBindPoint;
891 			0u,															//	uint32_t						viewMask;
892 			(needsIA ? 1u : 0u),										//	uint32_t						inputAttachmentCount;
893 			(needsIA ? &attachmentReferences.at(1) : nullptr),			//	const VkAttachmentReference*	pInputAttachments;
894 			1u,															//	uint32_t						colorAttachmentCount;
895 			&attachmentReferences.at(0),								//	const VkAttachmentReference*	pColorAttachments;
896 			nullptr,													//	const VkAttachmentReference*	pResolveAttachments;
897 			(needsDepthBuffer ? &attachmentReferences.at(1) : nullptr),	//	const VkAttachmentReference*	pDepthStencilAttachment;
898 			0u,															//	uint32_t						preserveAttachmentCount;
899 			nullptr,													//	const uint32_t*					pPreserveAttachments;
900 		};
901 
902 		const VkRenderPassCreateInfo2 renderPassCreateInfo =
903 		{
904 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,			//	VkStructureType					sType;
905 			nullptr,												//	const void*						pNext;
906 			0u,														//	VkRenderPassCreateFlags			flags;
907 			static_cast<uint32_t>(attachmentDescriptions.size()),	//	uint32_t						attachmentCount;
908 			de::dataOrNull(attachmentDescriptions),					//	const VkAttachmentDescription*	pAttachments;
909 			1u,														//	uint32_t						subpassCount;
910 			&subpassDesc,											//	const VkSubpassDescription*		pSubpasses;
911 			0u,														//	uint32_t						dependencyCount;
912 			nullptr,												//	const VkSubpassDependency*		pDependencies;
913 			0u,														//	uint32_t						correlatedViewMaskCount;
914 			nullptr,												//	const uint32_t*					pCorrelatedViewMasks;
915 		};
916 		renderPass = createRenderPass2(vkd, device, &renderPassCreateInfo);
917 	}
918 
919 	// Framebuffer.
920 	std::vector<VkImageView> framebufferViews;
921 
922 	framebufferViews.push_back(colorView.get());
923 	if (m_params.dsAttachmentNeeded())
924 		framebufferViews.push_back(dsImageView.get());
925 
926 	const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), static_cast<uint32_t>(framebufferViews.size()), de::dataOrNull(framebufferViews), extent.width, extent.height);
927 
928 	// Pipeline.
929 	std::vector<Move<VkPipeline>> graphicsPipelines;
930 	{
931 		const auto vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
932 		const auto fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
933 
934 		const VkPipelineVertexInputStateCreateInfo	vertexInputInfo		= initVulkanStructure();
935 		VkPipelineInputAssemblyStateCreateInfo		inputAssemblyInfo	= initVulkanStructure();
936 		VkPipelineViewportStateCreateInfo			viewportInfo		= initVulkanStructure();
937 		VkPipelineRasterizationStateCreateInfo		rasterizationInfo	= initVulkanStructure();
938 		VkPipelineMultisampleStateCreateInfo		multisampleInfo		= initVulkanStructure();
939 		VkPipelineDepthStencilStateCreateInfo		dsStateInfo			= initVulkanStructure();
940 		VkPipelineColorBlendStateCreateInfo			colorBlendInfo		= initVulkanStructure();
941 		VkPipelineColorBlendAttachmentState			colorBlendAttState	= {};
942 
943 		// Topology.
944 		inputAssemblyInfo.topology	= VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
945 
946 		// Viewports and scissors.
947 		const auto viewport			= makeViewport(extent);
948 		const auto scissor			= makeRect2D(extent);
949 		viewportInfo.viewportCount	= 1u;
950 		viewportInfo.pViewports		= &viewport;
951 		viewportInfo.scissorCount	= 1u;
952 		viewportInfo.pScissors		= &scissor;
953 
954 		// Line width.
955 		rasterizationInfo.lineWidth	= 1.0f;
956 
957 		// Multisample state.
958 		multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
959 
960 		// Depth/stencil state. This depends on the test parameters.
961 		if (m_params.needsDepthTest())
962 			dsStateInfo.depthTestEnable = VK_TRUE;
963 		if (depthWrites)
964 			dsStateInfo.depthWriteEnable = VK_TRUE;
965 		dsStateInfo.depthCompareOp = VK_COMPARE_OP_LESS;
966 		if (m_params.needsStencilTest())
967 			dsStateInfo.stencilTestEnable = VK_TRUE;
968 
969 		const auto stencilOpState	= makeStencilOpState(VK_STENCIL_OP_KEEP,												// failOp
970 														 (stencilWrites ? VK_STENCIL_OP_REPLACE : VK_STENCIL_OP_KEEP),		// passOp
971 														 VK_STENCIL_OP_KEEP,												// depthFailOp
972 														 VK_COMPARE_OP_LESS,												// compareOp
973 														 0xFFu,																// compareMask
974 														 (stencilWrites ? 0xFFu : 0u),										// writeMask
975 														 stencilFailVal);													// reference
976 		dsStateInfo.front			= stencilOpState;
977 		dsStateInfo.back			= stencilOpState;
978 
979 		colorBlendAttState.colorWriteMask	= (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
980 		colorBlendAttState.blendEnable		= VK_FALSE;
981 		colorBlendInfo.attachmentCount		= 1u;
982 		colorBlendInfo.pAttachments			= &colorBlendAttState;
983 
984 		graphicsPipelines.push_back(makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
985 			vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(), // Shader modules.
986 			renderPass.get(), 0u /*subpass*/,
987 			&vertexInputInfo, &inputAssemblyInfo, nullptr, &viewportInfo, &rasterizationInfo, &multisampleInfo, &dsStateInfo, &colorBlendInfo, nullptr));
988 
989 		// When the stencil test is enabled, we need a second pipeline changing the reference value so the stencil test passes the second time.
990 		if (m_params.needsStencilTest())
991 		{
992 			dsStateInfo.front.reference	= stencilPassVal;
993 			dsStateInfo.back.reference	= stencilPassVal;
994 
995 			graphicsPipelines.push_back(makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
996 				vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(), // Shader modules.
997 				renderPass.get(), 0u /*subpass*/,
998 				&vertexInputInfo, &inputAssemblyInfo, nullptr, &viewportInfo, &rasterizationInfo, &multisampleInfo, &dsStateInfo, &colorBlendInfo, nullptr));
999 		}
1000 	}
1001 
1002 	// Command pool and buffer.
1003 	const auto cmdPool		= makeCommandPool(vkd, device, qIndex);
1004 	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1005 	const auto cmdBuffer	= cmdBufferPtr.get();
1006 	const auto renderArea	= makeRect2D(extent);
1007 
1008 	// Output buffers to check the color attachment, depth/stencil attachment and output storage images.
1009 	using BufferPtr = de::MovePtr<BufferWithMemory>;
1010 
1011 	BufferPtr				colorVerifBuffer;
1012 	BufferPtr				depthVerifBuffer;
1013 	BufferPtr				stencilVerifBuffer;
1014 	std::vector<BufferPtr>	storageVerifBuffers;
1015 
1016 	{
1017 		const auto colorVerifBufferSize	= getCopyBufferSize(tcuColorFormat, extent);
1018 		const auto colorVerifBufferInfo	= makeBufferCreateInfo(colorVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1019 		colorVerifBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, colorVerifBufferInfo, MemoryRequirement::HostVisible));
1020 	}
1021 
1022 	if (hasDepth)
1023 	{
1024 		const auto depthVerifBufferSize	= getCopyBufferSize(tcuDepthFormat, extent);
1025 		const auto depthVerifBufferInfo	= makeBufferCreateInfo(depthVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1026 		depthVerifBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, depthVerifBufferInfo, MemoryRequirement::HostVisible));
1027 	}
1028 
1029 	if (hasStencil)
1030 	{
1031 		const auto stencilVerifBufferSize	= getCopyBufferSize(tcuStencilFormat, extent);
1032 		const auto stencilVerifBufferInfo	= makeBufferCreateInfo(stencilVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1033 		stencilVerifBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilVerifBufferInfo, MemoryRequirement::HostVisible));
1034 	}
1035 
1036 	storageVerifBuffers.reserve(descriptors.size());
1037 	for (const auto& desc : descriptors)
1038 	{
1039 		const auto storageFormat		= getAspectStorageFormat(desc.aspect);
1040 		const auto tcuStorageFormat		= mapVkFormat(storageFormat);
1041 		const auto descVerifBufferSize	= getCopyBufferSize(tcuStorageFormat, extent);
1042 		const auto descVerifBufferInfo	= makeBufferCreateInfo(descVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1043 		storageVerifBuffers.emplace_back(new BufferWithMemory(vkd, device, alloc, descVerifBufferInfo, MemoryRequirement::HostVisible));
1044 	}
1045 
1046 	beginCommandBuffer(vkd, cmdBuffer);
1047 
1048 	// Transition layout for output images.
1049 	std::vector<VkImageMemoryBarrier> outputImgBarriers;
1050 	for (const auto& outputImg : outputImages)
1051 		outputImgBarriers.push_back(makeImageMemoryBarrier(0u, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, outputImg->get(), colorSRR));
1052 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, static_cast<uint32_t>(outputImgBarriers.size()), de::dataOrNull(outputImgBarriers));
1053 
1054 	// Clear color and depth/stencil buffer.
1055 	const auto colorPreTransferBarrier	= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, colorBuffer.get(), colorSRR);
1056 	const auto dsPreTransferBarrier		= makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dsImage.get(), depthStencilSRR);
1057 	const std::vector<VkImageMemoryBarrier> preTransferBarriers = { colorPreTransferBarrier, dsPreTransferBarrier };
1058 
1059 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr,
1060 		static_cast<uint32_t>(preTransferBarriers.size()), de::dataOrNull(preTransferBarriers));
1061 
1062 	const auto colorClearValue	= makeClearValueColorVec4(colorClearVal);
1063 	const auto dsClearValue		= makeClearValueDepthStencil(depthClearValue, stencilClearVal);
1064 
1065 	vkd.cmdClearColorImage(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &colorClearValue.color, 1u, &colorSRR);
1066 	vkd.cmdClearDepthStencilImage(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &dsClearValue.depthStencil, 1u, &depthStencilSRR);
1067 
1068 	const auto graphicsAccesses			=	( VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
1069 											| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
1070 											| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
1071 											| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
1072 											| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT );
1073 	const auto colorPostTransferBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, graphicsAccesses, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, colorLayout, colorBuffer.get(), colorSRR);
1074 	const auto dsPostTransferBarrier	= makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, graphicsAccesses, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_params.layout, dsImage.get(), depthStencilSRR);
1075 	const std::vector<VkImageMemoryBarrier> postTransferBarriers = { colorPostTransferBarrier, dsPostTransferBarrier };
1076 
1077 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0u, 0u, nullptr, 0u, nullptr,
1078 		static_cast<uint32_t>(postTransferBarriers.size()), de::dataOrNull(postTransferBarriers));
1079 
1080 	// Render pass.
1081 	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea);
1082 
1083 	vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(),
1084 		0u, static_cast<uint32_t>(descriptorSets.size()), de::dataOrNull(descriptorSets), 0u, nullptr);
1085 
1086 	const auto useSecondDraw = m_params.depthBufferNeeded();
1087 
1088 	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelines.at(0).get());
1089 	{
1090 		if (useSecondDraw)
1091 		{
1092 			// Two draws: the first draw will use the red color.
1093 			pcData = PushConstantData(colorFailVal, (m_params.needsDepthTest() ? depthFailValue : depthPassValue));
1094 		}
1095 		else
1096 		{
1097 			// If there will be no more draws, the first one needs to pass and use the right color.
1098 			pcData = PushConstantData(colorPassVal, depthPassValue);
1099 		}
1100 
1101 		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &pcData);
1102 		vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1103 	}
1104 	if (useSecondDraw)
1105 	{
1106 		// The second draw, if used, always needs to pass and use the right color.
1107 		if (m_params.needsStencilTest())
1108 		{
1109 			// Pipeline with a good stencil reference value.
1110 			DE_ASSERT(graphicsPipelines.size() > 1);
1111 			vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelines.at(1).get());
1112 		}
1113 		pcData = PushConstantData(colorPassVal, depthPassValue);
1114 
1115 		vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &pcData);
1116 		vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1117 	}
1118 
1119 	endRenderPass(vkd, cmdBuffer);
1120 
1121 	// Copy color attachment.
1122 	{
1123 		const auto colorLayers				= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1124 		const auto copyRegion				= makeBufferImageCopy(extent, colorLayers);
1125 		const auto colorPostWriteBarrier	= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, colorLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
1126 		vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorPostWriteBarrier);
1127 		vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorVerifBuffer->get(), 1u, &copyRegion);
1128 	}
1129 
1130 	// Copy aspects of DS attachment.
1131 	{
1132 		const auto dsPostWriteBarrier	= makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, m_params.layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dsImage.get(), depthStencilSRR);
1133 		const auto fragmentTestStages	= (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1134 		vkd.cmdPipelineBarrier(cmdBuffer, fragmentTestStages, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &dsPostWriteBarrier);
1135 
1136 		if (hasDepth)
1137 		{
1138 			const auto depthLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u);
1139 			const auto copyRegion	= makeBufferImageCopy(extent, depthLayers);
1140 			vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, depthVerifBuffer->get(), 1u, &copyRegion);
1141 		}
1142 
1143 		if (hasStencil)
1144 		{
1145 			const auto stencilLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
1146 			const auto copyRegion		= makeBufferImageCopy(extent, stencilLayers);
1147 			vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stencilVerifBuffer->get(), 1u, &copyRegion);
1148 		}
1149 	}
1150 
1151 	// Copy storage images.
1152 	{
1153 		std::vector<VkImageMemoryBarrier> storagePostBarriers;
1154 		storagePostBarriers.reserve(outputImages.size());
1155 
1156 		for (const auto& outImg : outputImages)
1157 			storagePostBarriers.push_back(makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outImg->get(), colorSRR));
1158 
1159 		vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, static_cast<uint32_t>(storagePostBarriers.size()), de::dataOrNull(storagePostBarriers));
1160 
1161 		const auto colorLayers	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1162 		const auto copyRegion	= makeBufferImageCopy(extent, colorLayers);
1163 
1164 		DE_ASSERT(outputImages.size() == storageVerifBuffers.size());
1165 		for (size_t i = 0u; i < outputImages.size(); ++i)
1166 			vkd.cmdCopyImageToBuffer(cmdBuffer, outputImages[i]->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, storageVerifBuffers[i]->get(), 1u, &copyRegion);
1167 	}
1168 
1169 	// Transfer to host barrier for buffers.
1170 	const auto transferToHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1171 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &transferToHostBarrier, 0u, nullptr, 0u, nullptr);
1172 
1173 	endCommandBuffer(vkd, cmdBuffer);
1174 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1175 
1176 	// Verify the different buffers.
1177 	const tcu::IVec3 iExtent (static_cast<int>(extent.width), static_cast<int>(extent.height), static_cast<int>(extent.depth));
1178 	auto& log = m_context.getTestContext().getLog();
1179 
1180 	// Verify color buffer contents.
1181 	{
1182 		auto& verifAlloc = colorVerifBuffer->getAllocation();
1183 		invalidateAlloc(vkd, device, verifAlloc);
1184 
1185 		tcu::ConstPixelBufferAccess colorPixels(tcuColorFormat, iExtent, verifAlloc.getHostPtr());
1186 		if (!tcu::floatThresholdCompare(log, "ColorResult", "", colorPassVal, colorPixels, tcu::Vec4(0.0f), tcu::COMPARE_LOG_ON_ERROR))
1187 			TCU_FAIL("Unexpected color buffer contents; check log for details");
1188 	}
1189 
1190 	// Verify depth buffer contents.
1191 	if (hasDepth)
1192 	{
1193 		auto& verifAlloc = depthVerifBuffer->getAllocation();
1194 		invalidateAlloc(vkd, device, verifAlloc);
1195 
1196 		tcu::TextureLevel	referenceDepth	(tcuDepthFormat, iExtent.x(), iExtent.y(), iExtent.z());
1197 		auto				referenceAccess	= referenceDepth.getAccess();
1198 		const auto			refDepthVal		= (depthWrites ? depthPassValue : depthClearValue);
1199 
1200 		for (int z = 0; z < iExtent.z(); ++z)
1201 		for (int y = 0; y < iExtent.y(); ++y)
1202 		for (int x = 0; x < iExtent.x(); ++x)
1203 			referenceAccess.setPixDepth(refDepthVal, x, y, z);
1204 
1205 		tcu::ConstPixelBufferAccess depthPixels(tcuDepthFormat, iExtent, verifAlloc.getHostPtr());
1206 		if (!tcu::dsThresholdCompare(log, "DepthResult", "", referenceAccess, depthPixels, 0.1f, tcu::COMPARE_LOG_ON_ERROR))
1207 			TCU_FAIL("Unexpected value in depth buffer; check log for details");
1208 	}
1209 
1210 	// Verify stencil buffer contents.
1211 	if (hasStencil)
1212 	{
1213 		auto& verifAlloc = stencilVerifBuffer->getAllocation();
1214 		invalidateAlloc(vkd, device, verifAlloc);
1215 
1216 		tcu::TextureLevel	referenceStencil	(tcuStencilFormat, iExtent.x(), iExtent.y(), iExtent.z());
1217 		auto				referenceAccess		= referenceStencil.getAccess();
1218 		const auto			refStencilVal		= static_cast<int>(stencilWrites ? stencilPassVal : stencilClearVal);
1219 
1220 		for (int z = 0; z < iExtent.z(); ++z)
1221 		for (int y = 0; y < iExtent.y(); ++y)
1222 		for (int x = 0; x < iExtent.x(); ++x)
1223 			referenceAccess.setPixStencil(refStencilVal, x, y, z);
1224 
1225 		tcu::ConstPixelBufferAccess stencilPixels(tcuStencilFormat, iExtent, verifAlloc.getHostPtr());
1226 		if (!tcu::dsThresholdCompare(log, "StencilResult", "", referenceAccess, stencilPixels, 0.0f, tcu::COMPARE_LOG_ON_ERROR))
1227 			TCU_FAIL("Unexpected value in stencil buffer; check log for details");
1228 	}
1229 
1230 	// Verify output images.
1231 	for (size_t bufferIdx = 0u; bufferIdx < storageVerifBuffers.size(); ++bufferIdx)
1232 	{
1233 		const auto& verifBuffer = storageVerifBuffers[bufferIdx];
1234 		auto& verifAlloc = verifBuffer->getAllocation();
1235 		invalidateAlloc(vkd, device, verifAlloc);
1236 
1237 		const auto					bufferFormat	= getAspectStorageFormat(descriptors.at(bufferIdx).aspect);
1238 		const auto					tcuBufferFormat	= mapVkFormat(bufferFormat);
1239 		tcu::ConstPixelBufferAccess	colorPixels		(tcuBufferFormat, iExtent, verifAlloc.getHostPtr());
1240 		const std::string			resultName		= "Storage" + de::toString(bufferIdx);
1241 
1242 		if (descriptors.at(bufferIdx).aspect == VK_IMAGE_ASPECT_DEPTH_BIT)
1243 		{
1244 			if (!tcu::floatThresholdCompare(log, resultName.c_str(), "", tcu::Vec4(depthClearValue, 0.0f, 0.0f, 1.0f), colorPixels, tcu::Vec4(0.1f, 0.0f, 0.0f, 0.0f), tcu::COMPARE_LOG_ON_ERROR))
1245 				TCU_FAIL("Unexpected value in depth storage buffer " + de::toString(bufferIdx) + "; check log for details");
1246 		}
1247 		else if (descriptors.at(bufferIdx).aspect == VK_IMAGE_ASPECT_STENCIL_BIT)
1248 		{
1249 			tcu::TextureLevel stencilRef(tcuBufferFormat, iExtent.x(), iExtent.y(), iExtent.z());
1250 			auto colorPIxels = stencilRef.getAccess();
1251 
1252 			for (int z = 0; z < iExtent.z(); ++z)
1253 			for (int y = 0; y < iExtent.y(); ++y)
1254 			for (int x = 0; x < iExtent.x(); ++x)
1255 				colorPIxels.setPixel(tcu::UVec4(stencilClearVal, 0u, 0u, 0u), x, y, z);
1256 
1257 			if (!tcu::intThresholdCompare(log, resultName.c_str(), "", colorPIxels, colorPixels, tcu::UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1258 				TCU_FAIL("Unexpected value in stencil storage buffer " + de::toString(bufferIdx) + "; check log for details");
1259 		}
1260 		else
1261 			DE_ASSERT(false);
1262 	}
1263 
1264 	return tcu::TestStatus::pass("Pass");
1265 }
1266 
1267 } // anonymous
1268 
createImageDepthStencilDescriptorTests(tcu::TestContext & testCtx)1269 tcu::TestCaseGroup* createImageDepthStencilDescriptorTests (tcu::TestContext& testCtx)
1270 {
1271 	using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
1272 
1273 	const VkFormat kDepthStencilFormats[] =
1274 	{
1275 		VK_FORMAT_D16_UNORM,
1276 		VK_FORMAT_X8_D24_UNORM_PACK32,
1277 		VK_FORMAT_D32_SFLOAT,
1278 		VK_FORMAT_S8_UINT,
1279 		VK_FORMAT_D16_UNORM_S8_UINT,
1280 		VK_FORMAT_D24_UNORM_S8_UINT,
1281 		VK_FORMAT_D32_SFLOAT_S8_UINT,
1282 	};
1283 
1284 	// Layouts used in these tests as VkDescriptorImageInfo::imageLayout.
1285 	const VkImageLayout kTestedLayouts[] =
1286 	{
1287 		VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL,
1288 		VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL,
1289 		VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,
1290 		VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL,
1291 	};
1292 
1293 	// Types of read-only combinations to test.
1294 	ROAccessVec kReadOnlyDSAttachment		= { ReadOnlyAccess::DS_ATTACHMENT };
1295 	ROAccessVec kReadOnlyInputAttachment	= { ReadOnlyAccess::INPUT_ATTACHMENT };
1296 	ROAccessVec kReadOnlySampled			= { ReadOnlyAccess::SAMPLED };
1297 	ROAccessVec kReadOnlyDSSampled			= { ReadOnlyAccess::DS_ATTACHMENT, ReadOnlyAccess::SAMPLED };
1298 	ROAccessVec kReadOnlyInputSampled		= { ReadOnlyAccess::INPUT_ATTACHMENT, ReadOnlyAccess::SAMPLED };
1299 
1300 	const ROAccessVec* kROAccessCases[] =
1301 	{
1302 		&kReadOnlyDSAttachment,
1303 		&kReadOnlyInputAttachment,
1304 		&kReadOnlySampled,
1305 		&kReadOnlyDSSampled,
1306 		&kReadOnlyInputSampled,
1307 	};
1308 
1309 	const auto kLayoutPrefixLen = std::string("VK_IMAGE_LAYOUT_").size();
1310 	const auto kFormatPrefixLen = std::string("VK_FORMAT_").size();
1311 
1312 	TestCaseGroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "depth_stencil_descriptor", "Tests using depth/stencil images as descriptors"));
1313 
1314 	for (const auto& layout : kTestedLayouts)
1315 	{
1316 		const auto layoutStr		= de::toString(layout);
1317 		const auto layoutGroupName	= de::toLower(layoutStr.substr(kLayoutPrefixLen));
1318 		const auto layoutGroupDesc	= "Tests using the " + layoutStr + " layout";
1319 
1320 		TestCaseGroupPtr layoutGroup(new tcu::TestCaseGroup(testCtx, layoutGroupName.c_str(), layoutGroupDesc.c_str()));
1321 
1322 		for (const auto& format : kDepthStencilFormats)
1323 		{
1324 			const auto formatStr		= de::toString(format);
1325 			const auto formatGroupName	= de::toLower(formatStr.substr(kFormatPrefixLen));
1326 			const auto formatGroupDesc	= "Tests using the " + formatStr + " format";
1327 
1328 			TestCaseGroupPtr formatGroup(new tcu::TestCaseGroup(testCtx, formatGroupName.c_str(), formatGroupDesc.c_str()));
1329 
1330 			const auto depthAccess		= getLegalAccess(layout, VK_IMAGE_ASPECT_DEPTH_BIT);
1331 			const auto stencilAccess	= getLegalAccess(layout, VK_IMAGE_ASPECT_STENCIL_BIT);
1332 			const auto tcuFormat		= mapVkFormat(format);
1333 
1334 			const auto hasDepthAccess	= (depthAccess != AspectAccess::NONE);
1335 			const auto hasStencilAccess	= (stencilAccess != AspectAccess::NONE);
1336 			const auto hasDepth			= tcu::hasDepthComponent(tcuFormat.order);
1337 			const auto hasStencil		= tcu::hasStencilComponent(tcuFormat.order);
1338 
1339 			if (hasDepthAccess != hasDepth)
1340 				continue;
1341 			if (hasStencilAccess != hasStencil)
1342 				continue;
1343 
1344 			if (depthAccess == AspectAccess::RO)
1345 			{
1346 				for (const auto& depthROCase : kROAccessCases)
1347 				{
1348 					const std::string depthPart = "depth_" + de::toString(*depthROCase);
1349 					if (stencilAccess == AspectAccess::RO)
1350 					{
1351 						for (const auto& stencilROCase : kROAccessCases)
1352 						{
1353 							if (incompatibleInputAttachmentAccess(depthAccess, depthROCase, stencilAccess, stencilROCase))
1354 								continue;
1355 
1356 							const std::string stencilPart = "_stencil_" + de::toString(*stencilROCase);
1357 							const TestParams params =
1358 							{
1359 								format,						//	VkFormat				format;
1360 								layout,						//	VkImageLayout			layout;
1361 								depthAccess,				//	AspectAccess			depthAccess;
1362 								stencilAccess,				//	AspectAccess			stencilAccess;
1363 								tcu::just(*depthROCase),	//	tcu::Maybe<ROAccessVec>	depthROAccesses;
1364 								tcu::just(*stencilROCase),	//	tcu::Maybe<ROAccessVec>	stencilROAccesses;
1365 							};
1366 							formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, "", params));
1367 						}
1368 					}
1369 					else
1370 					{
1371 						if (incompatibleInputAttachmentAccess(depthAccess, depthROCase, stencilAccess, nullptr))
1372 							continue;
1373 
1374 						const std::string stencilPart = "_stencil_" + de::toString(stencilAccess);
1375 						const TestParams params =
1376 						{
1377 							format,							//	VkFormat				format;
1378 							layout,							//	VkImageLayout			layout;
1379 							depthAccess,					//	AspectAccess			depthAccess;
1380 							stencilAccess,					//	AspectAccess			stencilAccess;
1381 							tcu::just(*depthROCase),		//	tcu::Maybe<ROAccessVec>	depthROAccesses;
1382 							tcu::Nothing,					//	tcu::Maybe<ROAccessVec>	stencilROAccesses;
1383 						};
1384 						formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, "", params));
1385 					}
1386 				}
1387 			}
1388 			else
1389 			{
1390 				const std::string depthPart = "depth_" + de::toString(depthAccess);
1391 
1392 				if (stencilAccess == AspectAccess::RO)
1393 				{
1394 					for (const auto& stencilROCase : kROAccessCases)
1395 					{
1396 						if (incompatibleInputAttachmentAccess(depthAccess, nullptr, stencilAccess, stencilROCase))
1397 							continue;
1398 
1399 						const std::string stencilPart = "_stencil_" + de::toString(*stencilROCase);
1400 						const TestParams params =
1401 						{
1402 							format,							//	VkFormat				format;
1403 							layout,							//	VkImageLayout			layout;
1404 							depthAccess,					//	AspectAccess			depthAccess;
1405 							stencilAccess,					//	AspectAccess			stencilAccess;
1406 							tcu::Nothing,					//	tcu::Maybe<ROAccessVec>	depthROAccesses;
1407 							tcu::just(*stencilROCase),		//	tcu::Maybe<ROAccessVec>	stencilROAccesses;
1408 						};
1409 						formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, "", params));
1410 					}
1411 				}
1412 				else
1413 				{
1414 					if (incompatibleInputAttachmentAccess(depthAccess, nullptr, stencilAccess, nullptr))
1415 						continue;
1416 
1417 					const std::string stencilPart = "_stencil_" + de::toString(stencilAccess);
1418 					const TestParams params =
1419 					{
1420 						format,							//	VkFormat				format;
1421 						layout,							//	VkImageLayout			layout;
1422 						depthAccess,					//	AspectAccess			depthAccess;
1423 						stencilAccess,					//	AspectAccess			stencilAccess;
1424 						tcu::Nothing,					//	tcu::Maybe<ROAccessVec>	depthROAccesses;
1425 						tcu::Nothing,					//	tcu::Maybe<ROAccessVec>	stencilROAccesses;
1426 					};
1427 					formatGroup->addChild(new DepthStencilDescriptorCase(testCtx, depthPart + stencilPart, "", params));
1428 				}
1429 			}
1430 
1431 			layoutGroup->addChild(formatGroup.release());
1432 		}
1433 
1434 		mainGroup->addChild(layoutGroup.release());
1435 	}
1436 
1437 	return mainGroup.release();
1438 }
1439 
1440 } // image
1441 } // vkt
1442