• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 The Khronos Group Inc.
6  * Copyright (c) 2023 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 Fragment Shading Rate miscellaneous tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktFragmentShadingRateMiscTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 
28 #include "vkImageUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkBarrierUtil.hpp"
32 
33 #include "tcuImageCompare.hpp"
34 
35 #include "deUniquePtr.hpp"
36 
37 #include <sstream>
38 #include <vector>
39 #include <cstddef>
40 
41 namespace vkt
42 {
43 namespace FragmentShadingRate
44 {
45 
46 namespace
47 {
48 
49 using namespace vk;
50 
51 struct PositionColor
52 {
PositionColorvkt::FragmentShadingRate::__anonb99e3c9d0111::PositionColor53 	PositionColor (const tcu::Vec4& position_, const tcu::Vec4& color_)
54 		: position(position_), color(color_)
55 		{}
56 
57 	tcu::Vec4 position;
58 	tcu::Vec4 color;
59 };
60 
getDefaultExtent(void)61 VkExtent3D getDefaultExtent (void)
62 {
63 	return makeExtent3D(8u, 8u, 1u);
64 }
65 
checkShadingRateSupport(Context & context,bool pipeline=false,bool primitive=false,bool attachment=false)66 void checkShadingRateSupport (Context& context, bool pipeline = false, bool primitive = false, bool attachment = false)
67 {
68 	context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
69 	const auto& fsrFeatures = context.getFragmentShadingRateFeatures();
70 
71 	if (pipeline && !fsrFeatures.pipelineFragmentShadingRate)
72 		TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
73 
74 	if (primitive && !fsrFeatures.primitiveFragmentShadingRate)
75 		TCU_THROW(NotSupportedError, "primitiveFragmentShadingRate not supported");
76 
77 	if (attachment && !fsrFeatures.attachmentFragmentShadingRate)
78 		TCU_THROW(NotSupportedError, "attachmentFragmentShadingRate not supported");
79 }
80 
checkEnableDisableSupport(Context & context)81 void checkEnableDisableSupport (Context& context)
82 {
83 	checkShadingRateSupport(context, true, false, true);
84 }
85 
checkNoFragSupport(Context & context)86 void checkNoFragSupport (Context& context)
87 {
88 	checkShadingRateSupport(context, true);
89 }
90 
initDefaultVertShader(vk::SourceCollections & programCollection,const std::string & shaderName)91 void initDefaultVertShader (vk::SourceCollections& programCollection, const std::string& shaderName)
92 {
93 	// Default vertex shader, including vertex color.
94 	std::ostringstream vert;
95 	vert
96 		<< "#version 460\n"
97 		<< "#extension GL_EXT_fragment_shading_rate : enable\n"
98 		<< "layout (location=0) in vec4 inPos;\n"
99 		<< "layout (location=1) in vec4 inColor;\n"
100 		<< "layout (location=0) out vec4 outColor;\n"
101 		<< "void main (void) {\n"
102 		<< "    gl_Position = inPos;\n"
103 		<< "    outColor = inColor;\n"
104 		<< "}\n"
105 		;
106 	DE_ASSERT(!shaderName.empty());
107 	programCollection.glslSources.add(shaderName) << glu::VertexSource(vert.str());
108 }
109 
initDefaultFragShader(vk::SourceCollections & programCollection,const std::string & shaderName)110 void initDefaultFragShader (vk::SourceCollections& programCollection, const std::string& shaderName)
111 {
112 	// Default fragment shader, with vertex color.
113 	std::ostringstream frag;
114 	frag
115 		<< "#version 460\n"
116 		<< "layout (location=0) in vec4 inColor;\n"
117 		<< "layout (location=0) out vec4 outColor;\n"
118 		<< "void main (void) {\n"
119 		<< "    outColor = inColor;\n"
120 		<< "}\n"
121 		;
122 	DE_ASSERT(!shaderName.empty());
123 	programCollection.glslSources.add(shaderName) << glu::FragmentSource(frag.str());
124 }
125 
initEnableDisableShaders(vk::SourceCollections & programCollection)126 void initEnableDisableShaders (vk::SourceCollections& programCollection)
127 {
128 	initDefaultVertShader(programCollection, "vert");
129 	initDefaultFragShader(programCollection, "frag");
130 }
131 
initNoFragShaders(vk::SourceCollections & programCollection)132 void initNoFragShaders (vk::SourceCollections& programCollection)
133 {
134 	initDefaultVertShader(programCollection, "vert");
135 }
136 
getDefaultVertexInputStateCreateInfo(void)137 const VkPipelineVertexInputStateCreateInfo* getDefaultVertexInputStateCreateInfo (void)
138 {
139 	static VkVertexInputBindingDescription vertexBinding =
140 	{
141 		0u,												//	uint32_t			binding;
142 		static_cast<uint32_t>(sizeof(PositionColor)),	//	uint32_t			stride;
143 		VK_VERTEX_INPUT_RATE_VERTEX,					//	VkVertexInputRate	inputRate;
144 	};
145 
146 	static VkVertexInputAttributeDescription inputAttributes[] =
147 	{
148 		{
149 			// position
150 			0u,															//	uint32_t	location;
151 			0u,															//	uint32_t	binding;
152 			VK_FORMAT_R32G32B32A32_SFLOAT,								//	VkFormat	format;
153 			static_cast<uint32_t>(offsetof(PositionColor, position)),	//	uint32_t	offset;
154 		},
155 		{
156 			// color
157 			1u,															//	uint32_t	location;
158 			0u,															//	uint32_t	binding;
159 			VK_FORMAT_R32G32B32A32_SFLOAT,								//	VkFormat	format;
160 			static_cast<uint32_t>(offsetof(PositionColor, color)),		//	uint32_t	offset;
161 		},
162 	};
163 
164 	static const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
165 	{
166 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
167 		nullptr,													//	const void*									pNext;
168 		0u,															//	VkPipelineVertexInputStateCreateFlags		flags;
169 		1u,															//	uint32_t									vertexBindingDescriptionCount;
170 		&vertexBinding,												//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
171 		static_cast<uint32_t>(de::arrayLength(inputAttributes)),	//	uint32_t									vertexAttributeDescriptionCount;
172 		inputAttributes,											//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
173 	};
174 
175 	return &vertexInputStateCreateInfo;
176 }
177 
makeFragmentShadingRateStateCreateInfo(uint32_t width,uint32_t height,VkFragmentShadingRateCombinerOpKHR combiner0,VkFragmentShadingRateCombinerOpKHR combiner1)178 VkPipelineFragmentShadingRateStateCreateInfoKHR makeFragmentShadingRateStateCreateInfo (uint32_t width, uint32_t height, VkFragmentShadingRateCombinerOpKHR combiner0, VkFragmentShadingRateCombinerOpKHR combiner1)
179 {
180 	const VkPipelineFragmentShadingRateStateCreateInfoKHR fragmentShadingRateStateCreateInfo =
181 	{
182 		VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR,		//	VkStructureType						sType;
183 		nullptr,																	//	const void*							pNext;
184 		makeExtent2D(width, height),												//	VkExtent2D							fragmentSize;
185 		{																			//	VkFragmentShadingRateCombinerOpKHR	combinerOps[2];
186 			combiner0,
187 			combiner1,
188 		},
189 	};
190 
191 	return fragmentShadingRateStateCreateInfo;
192 }
193 
194 // Test idea: draw with VRS enabled by a fragment shading rate attachment, then bind a pipeline with VRS disabled and draw again.
195 // This was being incorrectly handled in RADV. Ref: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9005
testEnableDisable(Context & context)196 tcu::TestStatus testEnableDisable (Context& context)
197 {
198 	const auto			ctx				= context.getContextCommonData();
199 	const auto&			fsrProperties	= context.getFragmentShadingRateProperties();
200 	const auto&			minSize			= fsrProperties.minFragmentShadingRateAttachmentTexelSize;
201 	const auto&			maxSize			= fsrProperties.maxFragmentShadingRateAttachmentTexelSize;
202 	const auto			colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
203 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
204 	const auto			colorSRR		= makeDefaultImageSubresourceRange();
205 	const auto			colorSRL		= makeDefaultImageSubresourceLayers();
206 	const auto			bindPoint		= VK_PIPELINE_BIND_POINT_GRAPHICS;
207 	const auto			fsrFormat		= VK_FORMAT_R8_UINT;
208 	const auto			fsrExtent		= makeExtent3D(1u, 1u, 1u); // 1 pixel for the whole image.
209 	const auto			fsrUsage		= (VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR);
210 	const auto			sampleCount		= VK_SAMPLE_COUNT_1_BIT;
211 
212 	// Adjust image extent to an acceptable range so it's covered by a single FSR attachment pixel.
213 	auto				vkExtent		= getDefaultExtent();
214 	{
215 		de::clamp(vkExtent.width,	minSize.width,	maxSize.width);
216 		de::clamp(vkExtent.height,	minSize.height,	maxSize.height);
217 	}
218 	const tcu::IVec3	fbExtent		(static_cast<int>(vkExtent.width), static_cast<int>(vkExtent.height), static_cast<int>(vkExtent.depth));
219 
220 	vk::ImageWithBuffer colorBuffer (ctx.vkd, ctx.device, ctx.allocator, vkExtent, colorFormat, colorUsage, VK_IMAGE_TYPE_2D);
221 
222 	// Fragment shading rate attachment.
223 	const VkImageCreateInfo fsrAttachmentCreateInfo =
224 	{
225 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
226 		nullptr,								//	const void*				pNext;
227 		0u,										//	VkImageCreateFlags		flags;
228 		VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
229 		fsrFormat,								//	VkFormat				format;
230 		fsrExtent,								//	VkExtent3D				extent;
231 		1u,										//	uint32_t				mipLevels;
232 		1u,										//	uint32_t				arrayLayers;
233 		sampleCount,							//	VkSampleCountFlagBits	samples;
234 		VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
235 		fsrUsage,								//	VkImageUsageFlags		usage;
236 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
237 		0u,										//	uint32_t				queueFamilyIndexCount;
238 		nullptr,								//	const uint32_t*			pQueueFamilyIndices;
239 		VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
240 	};
241 	ImageWithMemory	fsrAttachment	(ctx.vkd, ctx.device, ctx.allocator, fsrAttachmentCreateInfo, MemoryRequirement::Any);
242 	const auto		fsrAttView		= makeImageView(ctx.vkd, ctx.device, fsrAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, fsrFormat, colorSRR);
243 
244 	const auto&	binaries	= context.getBinaryCollection();
245 	const auto	vertModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
246 	const auto	fragModule	= createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
247 
248 	const std::vector<VkAttachmentDescription2> attachmentDescriptions
249 	{
250 		// Color attachment.
251 		{
252 			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,		//	VkStructureType					sType;
253 			nullptr,										//	const void*						pNext;
254 			0u,												//	VkAttachmentDescriptionFlags	flags;
255 			colorFormat,									//	VkFormat						format;
256 			sampleCount,									//	VkSampleCountFlagBits			samples;
257 			VK_ATTACHMENT_LOAD_OP_CLEAR,					//	VkAttachmentLoadOp				loadOp;
258 			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
259 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
260 			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
261 			VK_IMAGE_LAYOUT_UNDEFINED,						//	VkImageLayout					initialLayout;
262 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					finalLayout;
263 		},
264 		// FSR attachment.
265 		{
266 			VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,						//	VkStructureType					sType;
267 			nullptr,														//	const void*						pNext;
268 			0u,																//	VkAttachmentDescriptionFlags	flags;
269 			fsrFormat,														//	VkFormat						format;
270 			sampleCount,													//	VkSampleCountFlagBits			samples;
271 			VK_ATTACHMENT_LOAD_OP_CLEAR,									//	VkAttachmentLoadOp				loadOp;
272 			VK_ATTACHMENT_STORE_OP_STORE,									//	VkAttachmentStoreOp				storeOp;
273 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								//	VkAttachmentLoadOp				stencilLoadOp;
274 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								//	VkAttachmentStoreOp				stencilStoreOp;
275 			VK_IMAGE_LAYOUT_UNDEFINED,										//	VkImageLayout					initialLayout;
276 			VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,	//	VkImageLayout					finalLayout;
277 		},
278 	};
279 
280 	const VkAttachmentReference2 colorAttRef =
281 	{
282 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,	//	VkStructureType		sType;
283 		nullptr,									//	const void*			pNext;
284 		0u,											//	uint32_t			attachment;
285 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout		layout;
286 		VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
287 	};
288 
289 	const VkAttachmentReference2 fsrAttRef =
290 	{
291 		VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,						//	VkStructureType		sType;
292 		nullptr,														//	const void*			pNext;
293 		1u,																//	uint32_t			attachment;
294 		VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,	//	VkImageLayout		layout;
295 		VK_IMAGE_ASPECT_COLOR_BIT,										//	VkImageAspectFlags	aspectMask;
296 	};
297 
298 	const VkFragmentShadingRateAttachmentInfoKHR fsrAttInfo =
299 	{
300 		VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,	//	VkStructureType					sType;
301 		nullptr,														//	const void*						pNext;
302 		&fsrAttRef,														//	const VkAttachmentReference2*	pFragmentShadingRateAttachment;
303 		makeExtent2D(vkExtent.width, vkExtent.height),					//	VkExtent2D						shadingRateAttachmentTexelSize;
304 	};
305 
306 	const VkSubpassDescription2 subpassDescription
307 	{
308 		VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,	//	VkStructureType					sType;
309 		&fsrAttInfo,								//	const void*						pNext;
310 		0u,											//	VkSubpassDescriptionFlags		flags;
311 		bindPoint,									//	VkPipelineBindPoint				pipelineBindPoint;
312 		0u,											//	uint32_t						viewMask;
313 		0u,											//	uint32_t						inputAttachmentCount;
314 		nullptr,									//	const VkAttachmentReference2*	pInputAttachments;
315 		1u,											//	uint32_t						colorAttachmentCount;
316 		&colorAttRef,								//	const VkAttachmentReference2*	pColorAttachments;
317 		nullptr,									//	const VkAttachmentReference2*	pResolveAttachments;
318 		nullptr,									//	const VkAttachmentReference2*	pDepthStencilAttachment;
319 		0u,											//	uint32_t						preserveAttachmentCount;
320 		nullptr,									//	const uint32_t*					pPreserveAttachments;
321 	};
322 
323 	const VkRenderPassCreateInfo2 renderPassCreateInfo =
324 	{
325 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,	//	VkStructureType					sType;
326 		nullptr,										//	const void*						pNext;
327 		0u,												//	VkRenderPassCreateFlags			flags;
328 		de::sizeU32(attachmentDescriptions),			//	uint32_t						attachmentCount;
329 		de::dataOrNull(attachmentDescriptions),			//	const VkAttachmentDescription2*	pAttachments;
330 		1u,												//	uint32_t						subpassCount;
331 		&subpassDescription,							//	const VkSubpassDescription2*	pSubpasses;
332 		0u,												//	uint32_t						dependencyCount;
333 		nullptr,										//	const VkSubpassDependency2*		pDependencies;
334 		0u,												//	uint32_t						correlatedViewMaskCount;
335 		nullptr,										//	const uint32_t*					pCorrelatedViewMasks;
336 	};
337 
338 	const auto renderPass = createRenderPass2(ctx.vkd, ctx.device, &renderPassCreateInfo);
339 
340 	const std::vector<VkImageView>	attachmentViews	{ colorBuffer.getImageView(), fsrAttView.get() };
341 	const auto						framebuffer		= makeFramebuffer(
342 		ctx.vkd, ctx.device, renderPass.get(),
343 		de::sizeU32(attachmentViews), de::dataOrNull(attachmentViews),
344 		vkExtent.width, vkExtent.height);
345 
346 	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
347 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
348 
349 	// Use the rate according to the attachment.
350 	const auto fragmentShadingRateStateCreateInfo = makeFragmentShadingRateStateCreateInfo(
351 		1u, 1u,
352 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
353 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR);
354 
355 	const std::vector<tcu::Vec4> vertices
356 	{
357 		tcu::Vec4(-1.0, -1.0f, 0.0f, 1.0f),
358 		tcu::Vec4(-1.0,  1.0f, 0.0f, 1.0f),
359 		tcu::Vec4( 1.0, -1.0f, 0.0f, 1.0f),
360 		tcu::Vec4( 1.0,  1.0f, 0.0f, 1.0f),
361 	};
362 
363 	const std::vector<tcu::Vec4> colors
364 	{
365 		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
366 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
367 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
368 		tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
369 	};
370 
371 	DE_ASSERT(vertices.size() == colors.size());
372 
373 	// We mix them reversing the color order for the first draw.
374 	std::vector<PositionColor> vrsVertices;
375 	std::vector<PositionColor> noVrsVertices;
376 
377 	vrsVertices.reserve(vertices.size());
378 	noVrsVertices.reserve(vertices.size());
379 
380 	for (size_t i = 0; i < vertices.size(); ++i)
381 	{
382 		vrsVertices.push_back(PositionColor(vertices.at(i), colors.at(colors.size() - 1 - i)));
383 		noVrsVertices.push_back(PositionColor(vertices.at(i), colors.at(i)));
384 	}
385 
386 	const auto vertexBufferSize			= static_cast<VkDeviceSize>(de::dataSize(vrsVertices));
387 	const auto vertexBufferUsage		= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
388 	const auto vertexBufferCreateInfo	= makeBufferCreateInfo(vertexBufferSize, vertexBufferUsage);
389 	const auto vertexBufferOffset		= static_cast<VkDeviceSize>(0);
390 
391 	BufferWithMemory vrsVerticesBuffer		(ctx.vkd, ctx.device, ctx.allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible);
392 	BufferWithMemory noVrsVerticesBuffer	(ctx.vkd, ctx.device, ctx.allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible);
393 	auto& vrsVertAlloc		= vrsVerticesBuffer.getAllocation();
394 	auto& noVrsVertAlloc	= noVrsVerticesBuffer.getAllocation();
395 
396 	deMemcpy(vrsVertAlloc.getHostPtr(), de::dataOrNull(vrsVertices), de::dataSize(vrsVertices));
397 	deMemcpy(noVrsVertAlloc.getHostPtr(), de::dataOrNull(noVrsVertices), de::dataSize(noVrsVertices));
398 	flushAlloc(ctx.vkd, ctx.device, vrsVertAlloc);
399 	flushAlloc(ctx.vkd, ctx.device, noVrsVertAlloc);
400 
401 	const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
402 
403 	// Pipeline with and without VRS.
404 	const auto pipelineVRS = makeGraphicsPipeline(ctx.vkd, ctx.device, pipelineLayout.get(),
405 		vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, fragModule.get(),
406 		renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u, 0u,
407 		getDefaultVertexInputStateCreateInfo(), nullptr, nullptr, nullptr, nullptr, nullptr, &fragmentShadingRateStateCreateInfo);
408 
409 	const auto pipelineNoVRS = makeGraphicsPipeline(ctx.vkd, ctx.device, pipelineLayout.get(),
410 		vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, fragModule.get(),
411 		renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u, 0u,
412 		getDefaultVertexInputStateCreateInfo());
413 
414 	CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
415 	const auto cmdBuffer = cmd.cmdBuffer.get();
416 
417 #if 0
418       const int gl_ShadingRateFlag2VerticalPixelsEXT = 1;
419       const int gl_ShadingRateFlag4VerticalPixelsEXT = 2;
420       const int gl_ShadingRateFlag2HorizontalPixelsEXT = 4;
421       const int gl_ShadingRateFlag4HorizontalPixelsEXT = 8;
422 #endif
423 	using ClearValueVec = std::vector<VkClearValue>;
424 	const uint32_t		clearAttRate		= 5u; // 2x2: (gl_ShadingRateFlag2HorizontalPixelsEXT | gl_ShadingRateFlag2VerticalPixelsEXT)
425 	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 0.0f);
426 	const ClearValueVec	clearValues
427 	{
428 		makeClearValueColor(clearColor),
429 		makeClearValueColorU32(clearAttRate, 0u, 0u, 0u),
430 	};
431 	const auto			colorCompThreshold	= 0.005f; // between 1/255 and 2/255.
432 	const tcu::Vec4		colorThreshold		(colorCompThreshold, colorCompThreshold, colorCompThreshold, colorCompThreshold);
433 	const auto			vertexCount			= de::sizeU32(vertices);
434 
435 	const struct
436 	{
437 		VkBuffer		vertexBuffer;
438 		VkPipeline		pipeline;
439 	} iterations[] =
440 	{
441 		{ vrsVerticesBuffer.get(),		pipelineVRS.get()	},
442 		{ noVrsVerticesBuffer.get(),	pipelineNoVRS.get()	},
443 	};
444 
445 	beginCommandBuffer(ctx.vkd, cmdBuffer);
446 	{
447 		// Render pass.
448 		beginRenderPass(ctx.vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), de::sizeU32(clearValues), de::dataOrNull(clearValues));
449 		for (const auto& iteration : iterations)
450 		{
451 			ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &iteration.vertexBuffer, &vertexBufferOffset);
452 			ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, iteration.pipeline);
453 			ctx.vkd.cmdDraw(cmdBuffer, vertexCount, 1u, 0u, 0u);
454 		}
455 		endRenderPass(ctx.vkd, cmdBuffer);
456 	}
457 	{
458 		// Copy image to verification buffer after rendering.
459 		const auto preTransferBarrier = makeImageMemoryBarrier(
460 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
461 			VK_ACCESS_TRANSFER_READ_BIT,
462 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
463 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
464 			colorBuffer.getImage(), colorSRR);
465 		cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preTransferBarrier);
466 		const auto copyRegion = makeBufferImageCopy(vkExtent, colorSRL);
467 		ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.getBuffer(), 1u, &copyRegion);
468 		const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
469 		cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
470 	}
471 	endCommandBuffer(ctx.vkd, cmdBuffer);
472 	submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
473 	invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
474 
475 	// Create expected reference image.
476 	const auto				tcuFormat		= mapVkFormat(colorFormat);
477 	tcu::TextureLevel		referenceLevel	(tcuFormat, fbExtent.x(), fbExtent.y());
478 	tcu::PixelBufferAccess	referenceAccess	= referenceLevel.getAccess();
479 
480 	const auto&	xSize	= fbExtent.x();
481 	const auto&	ySize	= fbExtent.y();
482 	const auto	xSizeF	= static_cast<float>(xSize);
483 	const auto	ySizeF	= static_cast<float>(ySize);
484 
485 	// This must match the vertex+color combination for the second draw.
486 	// Red goes from 0 to 1 on the X axis, Blue goes from 0 to 1 on the Y axis.
487 	for (int y = 0; y < fbExtent.y(); ++y)
488 		for (int x = 0; x < fbExtent.x(); ++x)
489 		{
490 			const float		red			= (static_cast<float>(y) + 0.5f) / ySizeF;
491 			const float		blue		= (static_cast<float>(x) + 0.5f) / xSizeF;
492 			const tcu::Vec4	refColor	(red, 0.0f, blue, 1.0f);
493 
494 			referenceAccess.setPixel(refColor, x, y);
495 		}
496 
497 	auto&								log				= context.getTestContext().getLog();
498 	const tcu::ConstPixelBufferAccess	resultAccess	(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
499 
500 	if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, colorThreshold, tcu::COMPARE_LOG_ON_ERROR))
501 		return tcu::TestStatus::fail("Unexpected color buffer contents -- check log for details");
502 	return tcu::TestStatus::pass("Pass");
503 }
504 
testNoFrag(Context & context)505 tcu::TestStatus testNoFrag (Context& context)
506 {
507 	const auto			ctx				= context.getContextCommonData();
508 	const auto			colorFormat		= VK_FORMAT_R8G8B8A8_UNORM;
509 	const auto			colorUsage		= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
510 	const auto			colorSRR		= makeDefaultImageSubresourceRange();
511 	const auto			colorSRL		= makeDefaultImageSubresourceLayers();
512 	const auto			depthFormat		= VK_FORMAT_D16_UNORM;
513 	const auto			depthUsage		= (VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
514 	const auto			depthSRR		= makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
515 	const auto			depthSRL		= makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, 1u);
516 	const auto			bindPoint		= VK_PIPELINE_BIND_POINT_GRAPHICS;
517 	const auto			vkExtent		= makeExtent3D(8u, 1u, 1u);
518 	const tcu::IVec3	fbExtent		(static_cast<int>(vkExtent.width), static_cast<int>(vkExtent.height), static_cast<int>(vkExtent.depth));
519 	const auto			imageType		= VK_IMAGE_TYPE_2D;
520 	const tcu::IVec2	tileSize		(2, 2);
521 
522 	vk::ImageWithBuffer colorBuffer (ctx.vkd, ctx.device, ctx.allocator, vkExtent, colorFormat, colorUsage, imageType, colorSRR);
523 	vk::ImageWithBuffer depthBuffer (ctx.vkd, ctx.device, ctx.allocator, vkExtent, depthFormat, depthUsage, imageType, depthSRR);
524 
525 	const auto vertModule = createShaderModule(ctx.vkd, ctx.device, context.getBinaryCollection().get("vert"));
526 	const auto renderPass = makeRenderPass(ctx.vkd, ctx.device, colorFormat, depthFormat);
527 
528 	const std::vector<VkImageView>	attachmentViews	{ colorBuffer.getImageView(), depthBuffer.getImageView() };
529 	const auto						framebuffer		= makeFramebuffer(
530 		ctx.vkd, ctx.device, renderPass.get(),
531 		de::sizeU32(attachmentViews), de::dataOrNull(attachmentViews),
532 		vkExtent.width, vkExtent.height);
533 
534 	const std::vector<VkViewport>	viewports	(1u, makeViewport(fbExtent));
535 	const std::vector<VkRect2D>		scissors	(1u, makeRect2D(fbExtent));
536 
537 	// Use the rate from the pipeline.
538 	const auto fragmentShadingRateStateCreateInfo = makeFragmentShadingRateStateCreateInfo(
539 		static_cast<uint32_t>(tileSize.x()), static_cast<uint32_t>(tileSize.y()), // This has mandatory support.
540 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
541 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR);
542 
543 	const std::vector<PositionColor> vertices
544 	{
545 		// Colors (second column) are irrelevant due to the lack of a frag shader.
546 		// In the first column we increase depth as we advance from left to right.
547 		{ tcu::Vec4(-1.0, -1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) },
548 		{ tcu::Vec4(-1.0,  1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f) },
549 		{ tcu::Vec4( 1.0, -1.0f, 1.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f) },
550 		{ tcu::Vec4( 1.0,  1.0f, 1.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f) },
551 	};
552 
553 	const auto vertexBufferSize			= static_cast<VkDeviceSize>(de::dataSize(vertices));
554 	const auto vertexBufferUsage		= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
555 	const auto vertexBufferCreateInfo	= makeBufferCreateInfo(vertexBufferSize, vertexBufferUsage);
556 	const auto vertexBufferOffset		= static_cast<VkDeviceSize>(0);
557 	BufferWithMemory vertexBuffer		(ctx.vkd, ctx.device, ctx.allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible);
558 	auto& vertexBufferAlloc				= vertexBuffer.getAllocation();
559 
560 	deMemcpy(vertexBufferAlloc.getHostPtr(), de::dataOrNull(vertices), de::dataSize(vertices));
561 	flushAlloc(ctx.vkd, ctx.device, vertexBufferAlloc);
562 
563 	const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device);
564 
565 	const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
566 	{
567 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType							sType;
568 		nullptr,													//	const void*								pNext;
569 		0u,															//	VkPipelineDepthStencilStateCreateFlags	flags;
570 		VK_TRUE,													//	VkBool32								depthTestEnable;
571 		VK_TRUE,													//	VkBool32								depthWriteEnable;
572 		VK_COMPARE_OP_ALWAYS,										//	VkCompareOp								depthCompareOp;
573 		VK_FALSE,													//	VkBool32								depthBoundsTestEnable;
574 		VK_FALSE,													//	VkBool32								stencilTestEnable;
575 		{},															//	VkStencilOpState						front;
576 		{},															//	VkStencilOpState						back;
577 		0.0f,														//	float									minDepthBounds;
578 		1.0f,														//	float									maxDepthBounds;
579 	};
580 
581 	// We need to force-enable rasterization at this step, otherwise the helper will disable it due to missing frag shader.
582 	const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
583 	{
584 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
585 		nullptr,													//	const void*								pNext;
586 		0u,															//	VkPipelineRasterizationStateCreateFlags	flags;
587 		VK_FALSE,													//	VkBool32								depthClampEnable;
588 		VK_FALSE,													//	VkBool32								rasterizerDiscardEnable;
589 		VK_POLYGON_MODE_FILL,										//	VkPolygonMode							polygonMode;
590 		VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
591 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace								frontFace;
592 		VK_FALSE,													//	VkBool32								depthBiasEnable;
593 		0.0f,														//	float									depthBiasConstantFactor;
594 		0.0f,														//	float									depthBiasClamp;
595 		0.0f,														//	float									depthBiasSlopeFactor;
596 		1.0f,														//	float									lineWidth;
597 	};
598 
599 	// Pipeline.
600 	const auto pipeline = makeGraphicsPipeline(ctx.vkd, ctx.device, pipelineLayout.get(),
601 		vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
602 		renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0u, 0u,
603 		getDefaultVertexInputStateCreateInfo(), &rasterizationStateCreateInfo, nullptr, &depthStencilStateCreateInfo, nullptr, nullptr, &fragmentShadingRateStateCreateInfo);
604 
605 	CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
606 	const auto cmdBuffer = cmd.cmdBuffer.get();
607 
608 	using ClearValueVec = std::vector<VkClearValue>;
609 	const tcu::Vec4		clearColor			(0.0f, 0.0f, 0.0f, 0.0f);
610 	const float			clearDepth			= 1.0f;
611 	const ClearValueVec	clearValues
612 	{
613 		makeClearValueColor(clearColor),
614 		makeClearValueDepthStencil(clearDepth, 0u),
615 	};
616 	const auto			colorCompThreshold	= 0.0f; // Expect exact results.
617 	const tcu::Vec4		colorThreshold		(colorCompThreshold, colorCompThreshold, colorCompThreshold, colorCompThreshold);
618 	const float			depthThreshold		= 0.000025f; // Between 1/65535 and 2/65535.
619 	const auto			vertexCount			= de::sizeU32(vertices);
620 
621 	beginCommandBuffer(ctx.vkd, cmdBuffer);
622 	{
623 		// Render pass.
624 		beginRenderPass(ctx.vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), de::sizeU32(clearValues), de::dataOrNull(clearValues));
625 		ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
626 		ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, pipeline.get());
627 		ctx.vkd.cmdDraw(cmdBuffer, vertexCount, 1u, 0u, 0u);
628 		endRenderPass(ctx.vkd, cmdBuffer);
629 	}
630 	{
631 		// Copy images to verification buffers after rendering.
632 		const std::vector<VkImageMemoryBarrier> preTransferBarriers =
633 		{
634 			makeImageMemoryBarrier(
635 						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
636 						VK_ACCESS_TRANSFER_READ_BIT,
637 						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
638 						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
639 						colorBuffer.getImage(), colorSRR),
640 
641 			makeImageMemoryBarrier(
642 						VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
643 						VK_ACCESS_TRANSFER_READ_BIT,
644 						VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
645 						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
646 						depthBuffer.getImage(), depthSRR),
647 		};
648 		const auto preTransferStages = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
649 		cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, preTransferStages, VK_PIPELINE_STAGE_TRANSFER_BIT, de::dataOrNull(preTransferBarriers), preTransferBarriers.size());
650 
651 		const auto copyColorRegion = makeBufferImageCopy(vkExtent, colorSRL);
652 		const auto copyDepthRegion = makeBufferImageCopy(vkExtent, depthSRL);
653 		ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.getBuffer(), 1u, &copyColorRegion);
654 		ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, depthBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, depthBuffer.getBuffer(), 1u, &copyDepthRegion);
655 
656 		const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
657 		cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &preHostBarrier);
658 	}
659 	endCommandBuffer(ctx.vkd, cmdBuffer);
660 	submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
661 	invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
662 	invalidateAlloc(ctx.vkd, ctx.device, depthBuffer.getBufferAllocation());
663 
664 	// Check results:
665 	// - Color image shouldn't have been touched.
666 	// - Depth buffer should have values in pairs of 2, within the accepted range.
667 	const auto colorTcuFormat = mapVkFormat(colorFormat);
668 	const auto depthTcuFormat = mapVkFormat(depthFormat);
669 	const tcu::ConstPixelBufferAccess colorResultAccess	(colorTcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
670 	const tcu::ConstPixelBufferAccess depthResultAccess (depthTcuFormat, fbExtent, depthBuffer.getBufferAllocation().getHostPtr());
671 
672 	auto& log = context.getTestContext().getLog();
673 	if (!tcu::floatThresholdCompare(log, "ColorResult", "", clearColor, colorResultAccess, colorThreshold, tcu::COMPARE_LOG_ON_ERROR))
674 		return tcu::TestStatus::fail("Unexpected color buffer contents (expected transparent black) -- check log for details");
675 
676 	// Note fragment shading rate does not affect the depth buffer, only frag shader invocations.
677 	// When verifying the depth buffer, we'll generate the reference values normally.
678 	tcu::TextureLevel refDepthLevel (depthTcuFormat, fbExtent.x(), fbExtent.y(), fbExtent.z());
679 	tcu::PixelBufferAccess refDepthAccess = refDepthLevel.getAccess();
680 	const float fWidth = static_cast<float>(fbExtent.x());
681 
682 	for (int y = 0; y < fbExtent.y(); ++y)
683 		for (int x = 0; x < fbExtent.x(); ++x)
684 		{
685 			// This needs to match vertex depths.
686 			const float depth = (static_cast<float>(x) + 0.5f) / fWidth;
687 			refDepthAccess.setPixDepth(depth, x, y);
688 		}
689 
690 	if (!tcu::dsThresholdCompare(log, "DepthResult", "", refDepthAccess, depthResultAccess, depthThreshold, tcu::COMPARE_LOG_ON_ERROR))
691 		return tcu::TestStatus::fail("Unexpected depth buffer contents -- check log for details");
692 
693 	return tcu::TestStatus::pass("Pass");
694 }
695 
696 } // anonymous
697 
createFragmentShadingRateMiscTests(tcu::TestCaseGroup * group)698 void createFragmentShadingRateMiscTests (tcu::TestCaseGroup* group)
699 {
700 	{
701 		const char* testName = "enable_disable_attachment";
702 		// Test drawing with VRS enabled by an attachment and then disabled
703 		addFunctionCaseWithPrograms(group, testName, checkEnableDisableSupport, initEnableDisableShaders, testEnableDisable);
704 	}
705 	{
706 		const char* testName = "no_frag_shader";
707 		// Test drawing with VRS enabled and no frag shader
708 		addFunctionCaseWithPrograms(group, testName, checkNoFragSupport, initNoFragShaders, testNoFrag);
709 	}
710 }
711 
712 } // FragmentShadingRate
713 } // vkt
714