• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 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 Test frag shader side effects are not removed by optimizations.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRasterizationFragShaderSideEffectsTests.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkQueryUtil.hpp"
29 #include "vkObjUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkImageWithMemory.hpp"
32 #include "vkBufferWithMemory.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkImageUtil.hpp"
37 
38 #include "tcuVector.hpp"
39 #include "tcuMaybe.hpp"
40 #include "tcuTestLog.hpp"
41 
42 #include "deUniquePtr.hpp"
43 
44 #include <sstream>
45 #include <string>
46 #include <memory>
47 #include <vector>
48 #include <algorithm>
49 
50 namespace vkt
51 {
52 namespace rasterization
53 {
54 
55 namespace
56 {
57 
58 enum class CaseType
59 {
60 	KILL,
61 	DEMOTE,
62 	TERMINATE_INVOCATION,
63 	SAMPLE_MASK_BEFORE,
64 	SAMPLE_MASK_AFTER,
65 	ALPHA_COVERAGE_BEFORE,
66 	ALPHA_COVERAGE_AFTER,
67 	DEPTH_BOUNDS,
68 	STENCIL_NEVER,
69 	DEPTH_NEVER,
70 };
71 
72 constexpr deUint32 kFramebufferWidth	= 32u;
73 constexpr deUint32 kFramebufferHeight	= 32u;
74 constexpr deUint32 kTotalPixels			= kFramebufferWidth * kFramebufferHeight;
75 
76 constexpr vk::VkFormatFeatureFlags	kNeededColorFeatures	= (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
77 constexpr vk::VkFormat				kColorFormat			= vk::VK_FORMAT_R8G8B8A8_UNORM;
78 constexpr vk::VkFormatFeatureFlags	kNeededDSFeatures		= vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
79 // VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT must be supported for one of these two, according to the spec.
80 const vk::VkFormat					kDepthStencilFormats[]	= { vk::VK_FORMAT_D32_SFLOAT_S8_UINT, vk::VK_FORMAT_D24_UNORM_S8_UINT };
81 
82 struct DepthBoundsParameters
83 {
84 	float minDepthBounds;
85 	float maxDepthBounds;
86 	float depthValue;
87 };
88 
89 struct TestParams
90 {
91 	CaseType							caseType;
92 	tcu::Vec4							clearColor;
93 	tcu::Vec4							drawColor;
94 	bool								colorAtEnd;
95 	tcu::Maybe<DepthBoundsParameters>	depthBoundsParams;
96 
TestParamsvkt::rasterization::__anonc8542df70111::TestParams97 	TestParams (CaseType type, const tcu::Vec4& clearColor_, const tcu::Vec4& drawColor_, bool colorAtEnd_, const tcu::Maybe<DepthBoundsParameters>& depthBoundsParams_)
98 		: caseType			(type)
99 		, clearColor		(clearColor_)
100 		, drawColor			(drawColor_)
101 		, colorAtEnd		(colorAtEnd_)
102 		, depthBoundsParams	(depthBoundsParams_)
103 	{
104 		if (caseType == CaseType::DEPTH_BOUNDS)
105 			DE_ASSERT(static_cast<bool>(depthBoundsParams));
106 	}
107 };
108 
expectClearColor(CaseType caseType)109 bool expectClearColor (CaseType caseType)
110 {
111 	return (caseType != CaseType::ALPHA_COVERAGE_BEFORE && caseType != CaseType::ALPHA_COVERAGE_AFTER);
112 }
113 
needsDepthStencilAttachment(CaseType caseType)114 bool needsDepthStencilAttachment (CaseType caseType)
115 {
116 	return (caseType == CaseType::DEPTH_BOUNDS || caseType == CaseType::DEPTH_NEVER || caseType == CaseType::STENCIL_NEVER);
117 }
118 
makeVkBool32(bool value)119 vk::VkBool32 makeVkBool32 (bool value)
120 {
121 	return (value ? VK_TRUE : VK_FALSE);
122 }
123 
124 class FragSideEffectsTestCase : public vkt::TestCase
125 {
126 public:
127 							FragSideEffectsTestCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
~FragSideEffectsTestCase(void)128 	virtual					~FragSideEffectsTestCase	(void) {}
129 
130 	virtual void			checkSupport				(Context& context) const;
131 	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
132 	virtual TestInstance*	createInstance				(Context& context) const;
133 
134 private:
135 	TestParams				m_params;
136 };
137 
138 class FragSideEffectsInstance : public vkt::TestInstance
139 {
140 public:
141 								FragSideEffectsInstance		(Context& context, const TestParams& params);
~FragSideEffectsInstance(void)142 	virtual						~FragSideEffectsInstance	(void) {}
143 
144 	virtual tcu::TestStatus		iterate						(void);
145 
146 private:
147 	TestParams					m_params;
148 };
149 
FragSideEffectsTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)150 FragSideEffectsTestCase::FragSideEffectsTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
151 	: vkt::TestCase	(testCtx, name, description)
152 	, m_params		(params)
153 {}
154 
checkSupport(Context & context) const155 void FragSideEffectsTestCase::checkSupport (Context& context) const
156 {
157 	const auto&	vki				= context.getInstanceInterface();
158 	const auto	physicalDevice	= context.getPhysicalDevice();
159 
160 	if (m_params.caseType == CaseType::DEPTH_BOUNDS)
161 	{
162 		const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
163 		if (!features.depthBounds)
164 			TCU_THROW(NotSupportedError, "Depth bounds test not supported");
165 	}
166 	else if (m_params.caseType == CaseType::DEMOTE)
167 	{
168 		context.requireDeviceFunctionality("VK_EXT_shader_demote_to_helper_invocation");
169 	}
170 	else if (m_params.caseType == CaseType::TERMINATE_INVOCATION)
171 	{
172 		context.requireDeviceFunctionality("VK_KHR_shader_terminate_invocation");
173 	}
174 
175 	const auto colorFormatProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kColorFormat);
176 	if ((colorFormatProperties.optimalTilingFeatures & kNeededColorFeatures) != kNeededColorFeatures)
177 		TCU_THROW(NotSupportedError, "Color format lacks required features");
178 }
179 
initPrograms(vk::SourceCollections & programCollection) const180 void FragSideEffectsTestCase::initPrograms (vk::SourceCollections& programCollection) const
181 {
182 	std::ostringstream headers;
183 	std::ostringstream before;
184 	std::ostringstream after;
185 
186 	std::ostringstream vert;
187 	std::ostringstream frag;
188 
189 	// Depth should be 0 by default unless provided by the depth bounds parameters.
190 	const float	meshDepth	= (m_params.depthBoundsParams ? m_params.depthBoundsParams.get().depthValue : 0.0f);
191 	const auto&	drawColor	= m_params.drawColor;
192 
193 	vert
194 		<< "#version 450\n"
195 		<< "\n"
196 		<< "layout (location=0) in vec2 inPos;\n"
197 		<< "\n"
198 		<< "void main() {\n"
199 		<< "    gl_Position = vec4(inPos, " << meshDepth << ", 1.0);\n"
200 		<< "}\n"
201 		;
202 
203 	// Prepare output color statement to be used before or after SSBO write.
204 	std::ostringstream colorStatement;
205 	if (m_params.caseType == CaseType::ALPHA_COVERAGE_BEFORE || m_params.caseType == CaseType::ALPHA_COVERAGE_AFTER)
206 	{
207 		// In the alpha coverage cases the alpha color value is supposed to be 0.
208 		DE_ASSERT(m_params.drawColor.w() == 0.0f);
209 
210 		// Leave out the alpha component for these cases.
211 		colorStatement << "    outColor.rgb = vec3(" << drawColor.x() << ", " << drawColor.y() << ", " << drawColor.z() << ");\n";
212 	}
213 	else
214 	{
215 		colorStatement << "    outColor = vec4(" << drawColor.x() << ", " << drawColor.y() << ", " << drawColor.z() << ", " << drawColor.w() << ");\n";
216 	}
217 
218 	switch (m_params.caseType)
219 	{
220 	case CaseType::KILL:
221 		after	<< "    discard;\n";
222 		break;
223 	case CaseType::DEMOTE:
224 		headers	<< "#extension GL_EXT_demote_to_helper_invocation : enable\n";
225 		after	<< "    demote;\n";
226 		break;
227 	case CaseType::TERMINATE_INVOCATION:
228 		headers	<< "#extension GL_EXT_terminate_invocation : enable\n";
229 		after	<< "    terminateInvocation;\n";
230 		break;
231 	case CaseType::SAMPLE_MASK_BEFORE:
232 		before	<< "    gl_SampleMask[0] = 0;\n";
233 		break;
234 	case CaseType::SAMPLE_MASK_AFTER:
235 		after	<< "    gl_SampleMask[0] = 0;\n";
236 		break;
237 	case CaseType::ALPHA_COVERAGE_BEFORE:
238 		before	<< "    outColor.a = float(" << drawColor.w() << ");\n";
239 		break;
240 	case CaseType::ALPHA_COVERAGE_AFTER:
241 		after	<< "    outColor.a = float(" << drawColor.w() << ");\n";
242 		break;
243 	case CaseType::DEPTH_BOUNDS:
244 	case CaseType::STENCIL_NEVER:
245 	case CaseType::DEPTH_NEVER:
246 		break;
247 	default:
248 		DE_ASSERT(false); break;
249 	}
250 
251 	frag
252 		<< "#version 450\n"
253 		<< "layout(set=0, binding=0, std430) buffer OutputBuffer {\n"
254 		<< "    int val[" << kTotalPixels << "];\n"
255 		<< "} outBuffer;\n"
256 		<< "layout (location=0) out vec4 outColor;\n"
257 		<< headers.str()
258 		<< "\n"
259 		<< "void main() {\n"
260 		<< "    const ivec2 fragCoord = ivec2(gl_FragCoord);\n"
261 		<< "    const int bufferIndex = (fragCoord.y * " << kFramebufferWidth << ") + fragCoord.x;\n"
262 		<< (m_params.colorAtEnd ? "" : colorStatement.str())
263 		<< before.str()
264 		<< "    outBuffer.val[bufferIndex] = 1;\n"
265 		<< after.str()
266 		<< (m_params.colorAtEnd ? colorStatement.str() : "")
267 		<< "}\n"
268 		;
269 
270 	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
271 	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
272 }
273 
createInstance(Context & context) const274 TestInstance* FragSideEffectsTestCase::createInstance (Context& context) const
275 {
276 	return new FragSideEffectsInstance(context, m_params);
277 }
278 
FragSideEffectsInstance(Context & context,const TestParams & params)279 FragSideEffectsInstance::FragSideEffectsInstance (Context& context, const TestParams& params)
280 	: vkt::TestInstance	(context)
281 	, m_params			(params)
282 {}
283 
iterate(void)284 tcu::TestStatus FragSideEffectsInstance::iterate (void)
285 {
286 	const auto&	vki				= m_context.getInstanceInterface();
287 	const auto	physicalDevice	= m_context.getPhysicalDevice();
288 	const auto&	vkd				= m_context.getDeviceInterface();
289 	const auto	device			= m_context.getDevice();
290 	auto&		alloc			= m_context.getDefaultAllocator();
291 	const auto	queue			= m_context.getUniversalQueue();
292 	const auto	queueIndex		= m_context.getUniversalQueueFamilyIndex();
293 
294 	// Color and depth/stencil images.
295 
296 	const vk::VkImageCreateInfo colorCreateInfo =
297 	{
298 		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											//	VkStructureType			sType;
299 		nullptr,																			//	const void*				pNext;
300 		0u,																					//	VkImageCreateFlags		flags;
301 		vk::VK_IMAGE_TYPE_2D,																//	VkImageType				imageType;
302 		kColorFormat,																		//	VkFormat				format;
303 		vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u),						//	VkExtent3D				extent;
304 		1u,																					//	deUint32				mipLevels;
305 		1u,																					//	deUint32				arrayLayers;
306 		vk::VK_SAMPLE_COUNT_1_BIT,															//	VkSampleCountFlagBits	samples;
307 		vk::VK_IMAGE_TILING_OPTIMAL,														//	VkImageTiling			tiling;
308 		(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT),	//	VkImageUsageFlags		usage;
309 		vk::VK_SHARING_MODE_EXCLUSIVE,														//	VkSharingMode			sharingMode;
310 		0u,																					//	deUint32				queueFamilyIndexCount;
311 		nullptr,																			//	const deUint32*			pQueueFamilyIndices;
312 		vk::VK_IMAGE_LAYOUT_UNDEFINED,														//	VkImageLayout			initialLayout;
313 	};
314 	vk::ImageWithMemory colorImage(vkd, device, alloc, colorCreateInfo, vk::MemoryRequirement::Any);
315 
316 	std::unique_ptr<vk::ImageWithMemory>	depthStencilImage;
317 	vk::VkFormat							depthStencilFormat = vk::VK_FORMAT_UNDEFINED;
318 
319 	if (needsDepthStencilAttachment(m_params.caseType))
320 	{
321 		// Find available image format first.
322 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(kDepthStencilFormats); ++i)
323 		{
324 			const auto dsFormatProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kDepthStencilFormats[i]);
325 			if ((dsFormatProperties.optimalTilingFeatures & kNeededDSFeatures) == kNeededDSFeatures)
326 			{
327 				depthStencilFormat = kDepthStencilFormats[i];
328 				break;
329 			}
330 		}
331 
332 		if (depthStencilFormat == vk::VK_FORMAT_UNDEFINED)
333 			TCU_FAIL("No suitable depth/stencil format found");
334 
335 		const vk::VkImageCreateInfo depthStencilCreateInfo =
336 		{
337 			vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											//	VkStructureType			sType;
338 			nullptr,																			//	const void*				pNext;
339 			0u,																					//	VkImageCreateFlags		flags;
340 			vk::VK_IMAGE_TYPE_2D,																//	VkImageType				imageType;
341 			depthStencilFormat,																	//	VkFormat				format;
342 			vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u),						//	VkExtent3D				extent;
343 			1u,																					//	deUint32				mipLevels;
344 			1u,																					//	deUint32				arrayLayers;
345 			vk::VK_SAMPLE_COUNT_1_BIT,															//	VkSampleCountFlagBits	samples;
346 			vk::VK_IMAGE_TILING_OPTIMAL,														//	VkImageTiling			tiling;
347 			vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,									//	VkImageUsageFlags		usage;
348 			vk::VK_SHARING_MODE_EXCLUSIVE,														//	VkSharingMode			sharingMode;
349 			0u,																					//	deUint32				queueFamilyIndexCount;
350 			nullptr,																			//	const deUint32*			pQueueFamilyIndices;
351 			vk::VK_IMAGE_LAYOUT_UNDEFINED,														//	VkImageLayout			initialLayout;
352 		};
353 
354 		depthStencilImage.reset(new vk::ImageWithMemory(vkd, device, alloc, depthStencilCreateInfo, vk::MemoryRequirement::Any));
355 	}
356 
357 	// Image views.
358 	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
359 	const auto colorImageView			= vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kColorFormat, colorSubresourceRange);
360 
361 	vk::Move<vk::VkImageView> depthStencilImageView;
362 	if (depthStencilImage)
363 	{
364 		const auto depthStencilSubresourceRange = vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
365 		depthStencilImageView = vk::makeImageView(vkd, device, depthStencilImage.get()->get(), vk::VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange);
366 	}
367 
368 	// Color image buffer.
369 	const auto tcuFormat			= vk::mapVkFormat(kColorFormat);
370 	const auto colorImageBufferSize	= static_cast<vk::VkDeviceSize>(kTotalPixels * tcuFormat.getPixelSize());
371 	const auto colorImageBufferInfo	= vk::makeBufferCreateInfo(colorImageBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
372 	vk::BufferWithMemory colorImageBuffer(vkd, device, alloc, colorImageBufferInfo, vk::MemoryRequirement::HostVisible);
373 
374 	// Vertex buffer.
375 	const std::vector<tcu::Vec2> fullScreenQuad =
376 	{
377 		tcu::Vec2(-1.0f,  1.0f),
378 		tcu::Vec2( 1.0f,  1.0f),
379 		tcu::Vec2( 1.0f, -1.0f),
380 		tcu::Vec2(-1.0f,  1.0f),
381 		tcu::Vec2( 1.0f, -1.0f),
382 		tcu::Vec2(-1.0f, -1.0f),
383 	};
384 
385 	const auto				vertexBufferSize	= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
386 	const auto				vertexBufferInfo	= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
387 	const vk::VkDeviceSize	vertexBufferOffset	= 0ull;
388 	vk::BufferWithMemory	vertexBuffer		(vkd, device, alloc, vertexBufferInfo, vk::MemoryRequirement::HostVisible);
389 	const auto&				vertexBufferAlloc	= vertexBuffer.getAllocation();
390 
391 	deMemcpy(vertexBufferAlloc.getHostPtr(), fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
392 	vk::flushAlloc(vkd, device, vertexBufferAlloc);
393 
394 	// Storage buffer.
395 	const auto				storageBufferSize	= static_cast<vk::VkDeviceSize>(kTotalPixels * sizeof(deInt32));
396 	const auto				storageBufferInfo	= vk::makeBufferCreateInfo(storageBufferSize, (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT));
397 	vk::BufferWithMemory	storageBuffer		(vkd, device, alloc, storageBufferInfo, vk::MemoryRequirement::HostVisible);
398 	const auto&				storageBufferAlloc	= storageBuffer.getAllocation();
399 
400 	deMemset(storageBufferAlloc.getHostPtr(), 0, static_cast<size_t>(storageBufferSize));
401 	vk::flushAlloc(vkd, device, storageBufferAlloc);
402 
403 	// Descriptor set layout.
404 	vk::DescriptorSetLayoutBuilder layoutBuilder;
405 	layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
406 	const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
407 
408 	// Pipeline layout.
409 	const auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
410 
411 	// Descriptor pool.
412 	vk::DescriptorPoolBuilder poolBuilder;
413 	poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
414 	const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
415 
416 	// Descriptor set.
417 	const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
418 
419 	// Update descriptor set.
420 	vk::DescriptorSetUpdateBuilder	updateBuilder;
421 	const auto						descriptorBufferInfo = vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, storageBufferSize);
422 	updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo);
423 	updateBuilder.update(vkd, device);
424 
425 	// Render pass.
426 	const auto renderPass = vk::makeRenderPass(vkd, device, kColorFormat, depthStencilFormat);
427 
428 	// Framebuffer.
429 	std::vector<vk::VkImageView> imageViews(1u, colorImageView.get());
430 	if (depthStencilImage)
431 		imageViews.push_back(depthStencilImageView.get());
432 
433 	const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(imageViews.size()), imageViews.data(), kFramebufferWidth, kFramebufferHeight);
434 
435 	// Shader modules.
436 	const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
437 	const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
438 
439 	// Vertex input state.
440 	const auto vertexBinding	= vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(sizeof(tcu::Vec2)), vk::VK_VERTEX_INPUT_RATE_VERTEX);
441 	const auto vertexAttributes	= vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u);
442 
443 	const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo =
444 	{
445 		vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
446 		nullptr,														//	const void*									pNext;
447 		0u,																//	VkPipelineVertexInputStateCreateFlags		flags;
448 		1u,																//	deUint32									vertexBindingDescriptionCount;
449 		&vertexBinding,													//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
450 		1u,																//	deUint32									vertexAttributeDescriptionCount;
451 		&vertexAttributes,												//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
452 	};
453 
454 	// Input assembly state.
455 	const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo =
456 	{
457 		vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType							sType;
458 		nullptr,															//	const void*								pNext;
459 		0u,																	//	VkPipelineInputAssemblyStateCreateFlags	flags;
460 		vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,							//	VkPrimitiveTopology						topology;
461 		VK_FALSE,															//	VkBool32								primitiveRestartEnable;
462 	};
463 
464 	// Viewport state.
465 	const auto viewport	= vk::makeViewport(kFramebufferWidth, kFramebufferHeight);
466 	const auto scissor	= vk::makeRect2D(kFramebufferWidth, kFramebufferHeight);
467 
468 	const vk::VkPipelineViewportStateCreateInfo viewportInfo =
469 	{
470 		vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	//	VkStructureType						sType;
471 		nullptr,													//	const void*							pNext;
472 		0u,															//	VkPipelineViewportStateCreateFlags	flags;
473 		1u,															//	deUint32							viewportCount;
474 		&viewport,													//	const VkViewport*					pViewports;
475 		1u,															//	deUint32							scissorCount;
476 		&scissor,													//	const VkRect2D*						pScissors;
477 	};
478 
479 	// Rasterization state.
480 	const vk::VkPipelineRasterizationStateCreateInfo rasterizationInfo =
481 	{
482 		vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType							sType;
483 		nullptr,														//	const void*								pNext;
484 		0u,																//	VkPipelineRasterizationStateCreateFlags	flags;
485 		VK_FALSE,														//	VkBool32								depthClampEnable;
486 		VK_FALSE,														//	VkBool32								rasterizerDiscardEnable;
487 		vk::VK_POLYGON_MODE_FILL,										//	VkPolygonMode							polygonMode;
488 		vk::VK_CULL_MODE_NONE,											//	VkCullModeFlags							cullMode;
489 		vk::VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace								frontFace;
490 		VK_FALSE,														//	VkBool32								depthBiasEnable;
491 		0.0f,															//	float									depthBiasConstantFactor;
492 		0.0f,															//	float									depthBiasClamp;
493 		0.0f,															//	float									depthBiasSlopeFactor;
494 		1.0f,															//	float									lineWidth;
495 	};
496 
497 	// Multisample state.
498 	const bool										alphaToCoverageEnable	= (m_params.caseType == CaseType::ALPHA_COVERAGE_BEFORE || m_params.caseType == CaseType::ALPHA_COVERAGE_AFTER);
499 	const vk::VkPipelineMultisampleStateCreateInfo	multisampleInfo			=
500 	{
501 		vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
502 		nullptr,														//	const void*								pNext;
503 		0u,																//	VkPipelineMultisampleStateCreateFlags	flags;
504 		vk::VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
505 		VK_FALSE,														//	VkBool32								sampleShadingEnable;
506 		0.0f,															//	float									minSampleShading;
507 		nullptr,														//	const VkSampleMask*						pSampleMask;
508 		makeVkBool32(alphaToCoverageEnable),							//	VkBool32								alphaToCoverageEnable;
509 		VK_FALSE,														//	VkBool32								alphaToOneEnable;
510 	};
511 
512 	// Depth/stencil state.
513 	const auto enableDepthBounds		= makeVkBool32(m_params.caseType == CaseType::DEPTH_BOUNDS);
514 	const auto enableDepthStencilTest	= static_cast<bool>(depthStencilImage);
515 
516 	const auto depthCompareOp			= ((m_params.caseType == CaseType::DEPTH_NEVER) ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
517 	const auto stencilCompareOp			= ((m_params.caseType == CaseType::STENCIL_NEVER) ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
518 	const auto stencilOpState			= vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, stencilCompareOp, 0xFFu, 0xFFu, 0u);
519 
520 	const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo =
521 	{
522 		vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,					//	VkStructureType							sType;
523 		nullptr,																		//	const void*								pNext;
524 		0u,																				//	VkPipelineDepthStencilStateCreateFlags	flags;
525 		enableDepthStencilTest,															//	VkBool32								depthTestEnable;
526 		enableDepthStencilTest,															//	VkBool32								depthWriteEnable;
527 		depthCompareOp,																	//	VkCompareOp								depthCompareOp;
528 		enableDepthBounds,																//	VkBool32								depthBoundsTestEnable;
529 		enableDepthStencilTest,															//	VkBool32								stencilTestEnable;
530 		stencilOpState,																	//	VkStencilOpState						front;
531 		stencilOpState,																	//	VkStencilOpState						back;
532 		(enableDepthBounds ? m_params.depthBoundsParams.get().minDepthBounds : 0.0f),	//	float									minDepthBounds;
533 		(enableDepthBounds ? m_params.depthBoundsParams.get().maxDepthBounds : 1.0f),	//	float									maxDepthBounds;
534 	};
535 
536 	// Color blend state.
537 	const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
538 	{
539 		VK_FALSE,						// VkBool32                 blendEnable
540 		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor            srcColorBlendFactor
541 		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor            dstColorBlendFactor
542 		vk::VK_BLEND_OP_ADD,			// VkBlendOp                colorBlendOp
543 		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor            srcAlphaBlendFactor
544 		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor            dstAlphaBlendFactor
545 		vk::VK_BLEND_OP_ADD,			// VkBlendOp                alphaBlendOp
546 		vk::VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags    colorWriteMask
547 		| vk::VK_COLOR_COMPONENT_G_BIT
548 		| vk::VK_COLOR_COMPONENT_B_BIT
549 		| vk::VK_COLOR_COMPONENT_A_BIT
550 	};
551 
552 	const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo =
553 	{
554 		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
555 		nullptr,														//	const void*									pNext;
556 		0u,																//	VkPipelineColorBlendStateCreateFlags		flags;
557 		VK_FALSE,														//	VkBool32									logicOpEnable;
558 		vk::VK_LOGIC_OP_NO_OP,											//	VkLogicOp									logicOp;
559 		1u,																//	deUint32									attachmentCount;
560 		&colorBlendAttachmentState,										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
561 		{ .0f, .0f, .0f, .0f },											//	float										blendConstants[4];
562 	};
563 
564 	// Graphics pipeline.
565 	const auto graphicsPipeline = vk::makeGraphicsPipeline(
566 		vkd, device, pipelineLayout.get(),
567 		vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
568 		renderPass.get(), 0u,
569 		&vertexInputInfo,
570 		&inputAssemblyInfo,
571 		nullptr,
572 		&viewportInfo,
573 		&rasterizationInfo,
574 		&multisampleInfo,
575 		&depthStencilInfo,
576 		&colorBlendInfo);
577 
578 	// Command buffer.
579 	const auto cmdPool		= vk::makeCommandPool(vkd, device, queueIndex);
580 	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
581 	const auto cmdBuffer	= cmdBufferPtr.get();
582 
583 	// Draw full-screen quad.
584 	std::vector<vk::VkClearValue> clearValues;
585 	clearValues.push_back(vk::makeClearValueColor(m_params.clearColor));
586 	clearValues.push_back(vk::makeClearValueDepthStencil(1.0f, 0u));
587 
588 	vk::beginCommandBuffer(vkd, cmdBuffer);
589 	vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
590 	vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
591 	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
592 	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
593 	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
594 	vk::endRenderPass(vkd, cmdBuffer);
595 
596 	// Image and buffer barriers.
597 
598 	// Storage buffer frag-write to host-read barrier.
599 	const auto storageBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0u, VK_WHOLE_SIZE);
600 
601 	// Color image frag-write to transfer-read barrier.
602 	const auto colorImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImage.get(), colorSubresourceRange);
603 
604 	// Color buffer transfer-write to host-read barrier.
605 	const auto colorBufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, colorImageBuffer.get(), 0u, VK_WHOLE_SIZE);
606 
607 	vk::cmdPipelineBufferMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &storageBufferBarrier);
608 	vk::cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &colorImageBarrier);
609 	const auto copyRegion = vk::makeBufferImageCopy(vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u), vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
610 	vkd.cmdCopyImageToBuffer(cmdBuffer, colorImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorImageBuffer.get(), 1u, &copyRegion);
611 	vk::cmdPipelineBufferMemoryBarrier(vkd, cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, &colorBufferBarrier);
612 
613 	vk::endCommandBuffer(vkd, cmdBuffer);
614 	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
615 
616 	// Check output.
617 	{
618 		// Check SSBO contents.
619 		vk::invalidateAlloc(vkd, device, storageBufferAlloc);
620 		const auto bufferElements = reinterpret_cast<const deInt32*>(storageBufferAlloc.getHostPtr());
621 
622 		for (deUint32 i = 0; i < kTotalPixels; ++i)
623 		{
624 			if (bufferElements[i] != 1)
625 			{
626 				std::ostringstream msg;
627 				msg << "Unexpected value in storage buffer element " << i;
628 				return tcu::TestStatus::fail("Fail: " + msg.str());
629 			}
630 		}
631 	}
632 
633 	{
634 		// Check color attachment.
635 		std::vector<tcu::Vec4> expectedColors(1u, m_params.clearColor);
636 		if (!expectClearColor(m_params.caseType))
637 			expectedColors.push_back(m_params.drawColor);
638 
639 		const auto& colorImageBufferAlloc = colorImageBuffer.getAllocation();
640 		vk::invalidateAlloc(vkd, device, colorImageBufferAlloc);
641 
642 		const auto iWidth	= static_cast<int>(kFramebufferWidth);
643 		const auto iHeight	= static_cast<int>(kFramebufferHeight);
644 
645 		tcu::ConstPixelBufferAccess colorPixels		(tcuFormat, iWidth, iHeight, 1, colorImageBufferAlloc.getHostPtr());
646 		std::vector<deUint8>		errorMaskBuffer	(kTotalPixels * tcuFormat.getPixelSize(), 0u);
647 		tcu::PixelBufferAccess		errorMask		(tcuFormat, iWidth, iHeight, 1, errorMaskBuffer.data());
648 		const tcu::Vec4				green			(0.0f, 1.0f, 0.0f, 1.0f);
649 		const tcu::Vec4				red				(1.0f, 0.0f, 0.0f, 1.0f);
650 		bool						allPixOk		= true;
651 
652 		for (int i = 0; i < iWidth; ++i)
653 		for (int j = 0; j < iHeight; ++j)
654 		{
655 			const auto pixel = colorPixels.getPixel(i, j);
656 			const bool pixOk = std::any_of(begin(expectedColors), end(expectedColors), [&pixel](const tcu::Vec4& expected) -> bool { return (pixel == expected); });
657 			errorMask.setPixel((pixOk ? green : red), i, j);
658 			if (!pixOk)
659 				allPixOk = false;
660 		}
661 
662 		if (!allPixOk)
663 		{
664 			auto& testLog = m_context.getTestContext().getLog();
665 			testLog << tcu::TestLog::Image("ColorBuffer", "Result color buffer", colorPixels);
666 			testLog << tcu::TestLog::Image("ErrorMask", "Error mask with errors marked in red", errorMask);
667 			return tcu::TestStatus::fail("Fail: color buffer with unexpected values; check logged images");
668 		}
669 	}
670 
671 	return tcu::TestStatus::pass("Pass");
672 }
673 
674 } // anonymous
675 
createFragSideEffectsTests(tcu::TestContext & testCtx)676 tcu::TestCaseGroup* createFragSideEffectsTests (tcu::TestContext& testCtx)
677 {
678 	de::MovePtr<tcu::TestCaseGroup> fragSideEffectsGroup(new tcu::TestCaseGroup(testCtx, "frag_side_effects", "Test fragment shader side effects are not removed by optimizations"));
679 
680 	const tcu::Vec4		kDefaultClearColor			(0.0f, 0.0f, 0.0f, 1.0f);
681 	const tcu::Vec4		kDefaultDrawColor			(0.0f, 0.0f, 1.0f, 1.0f);
682 	const auto			kDefaultDepthBoundsParams	= tcu::nothing<DepthBoundsParameters>();
683 
684 	static const struct
685 	{
686 		bool		colorAtEnd;
687 		std::string	name;
688 		std::string	desc;
689 	} kColorOrders[] =
690 	{
691 		{ false,	"color_at_beginning",	"Fragment shader output assignment at the beginning of the shader"	},
692 		{ true,		"color_at_end",			"Fragment shader output assignment at the end of the shader"		},
693 	};
694 
695 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(kColorOrders); ++i)
696 	{
697 		de::MovePtr<tcu::TestCaseGroup> colorOrderGroup(new tcu::TestCaseGroup(testCtx, kColorOrders[i].name.c_str(), kColorOrders[i].desc.c_str()));
698 		const bool colorAtEnd = kColorOrders[i].colorAtEnd;
699 
700 		{
701 			TestParams params(CaseType::KILL, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
702 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "kill", "OpKill after SSBO write", params));
703 		}
704 		{
705 			TestParams params(CaseType::DEMOTE, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
706 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "demote", "OpDemoteToHelperInvocation after SSBO write", params));
707 		}
708 		{
709 			TestParams params(CaseType::TERMINATE_INVOCATION, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
710 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "terminate_invocation", "OpTerminateInvocation after SSBO write", params));
711 		}
712 		{
713 			TestParams params(CaseType::SAMPLE_MASK_BEFORE, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
714 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "sample_mask_before", "Set sample mask to zero before SSBO write", params));
715 		}
716 		{
717 			TestParams params(CaseType::SAMPLE_MASK_AFTER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
718 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "sample_mask_after", "Set sample mask to zero after SSBO write", params));
719 		}
720 		{
721 			TestParams params(CaseType::STENCIL_NEVER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
722 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "stencil_never", "SSBO write with stencil test never passes", params));
723 		}
724 		{
725 			TestParams params(CaseType::DEPTH_NEVER, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, kDefaultDepthBoundsParams);
726 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "depth_never", "SSBO write with depth test never passes", params));
727 		}
728 		{
729 			const tcu::Vec4	drawColor(kDefaultDrawColor.x(), kDefaultDrawColor.y(), kDefaultDrawColor.z(), 0.0f);
730 			{
731 				TestParams params(CaseType::ALPHA_COVERAGE_BEFORE, kDefaultClearColor, drawColor, colorAtEnd, kDefaultDepthBoundsParams);
732 				colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "alpha_coverage_before", "Enable alpha coverage and draw with alpha zero before SSBO write", params));
733 			}
734 			{
735 				TestParams params(CaseType::ALPHA_COVERAGE_AFTER, kDefaultClearColor, drawColor, colorAtEnd, kDefaultDepthBoundsParams);
736 				colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "alpha_coverage_after", "Enable alpha coverage and draw with alpha zero after SSBO write", params));
737 			}
738 		}
739 		{
740 			DepthBoundsParameters depthBoundsParams = {0.25f, 0.5f, 0.75f}; // min, max, draw depth.
741 			TestParams params(CaseType::DEPTH_BOUNDS, kDefaultClearColor, kDefaultDrawColor, colorAtEnd, tcu::just(depthBoundsParams));
742 			colorOrderGroup->addChild(new FragSideEffectsTestCase(testCtx, "depth_bounds", "SSBO write with depth bounds test failing", params));
743 		}
744 
745 		fragSideEffectsGroup->addChild(colorOrderGroup.release());
746 	}
747 
748 	return fragSideEffectsGroup.release();
749 }
750 
751 } // rasterization
752 } // vkt
753