• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 LunarG, Inc.
6  * Copyright (c) 2022 The Khronos Group Inc.
7  * Copyright (c) 2022 Google LLC
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Dynamic State Discard Tests
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktDynamicStateDiscardTests.hpp"
27 
28 #include "vktDynamicStateBaseClass.hpp"
29 #include "vktDynamicStateTestCaseUtil.hpp"
30 
31 #include "vkImageUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 
34 #include "tcuImageCompare.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuRGBA.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkBufferWithMemory.hpp"
41 
42 namespace vkt
43 {
44 namespace DynamicState
45 {
46 using namespace Draw;
47 using namespace vk;
48 
49 enum TestDynamicStateDiscard
50 {
51 	TEST_STENCIL,
52 	TEST_VIEWPORT,
53 	TEST_SCISSOR,
54 	TEST_DEPTH,
55 	TEST_BLEND_CONSTANTS,
56 	TEST_LINE_WIDTH,
57 };
58 
pickSupportedStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device)59 VkFormat pickSupportedStencilFormat	(const InstanceInterface&	instanceInterface,
60 									 const VkPhysicalDevice		device)
61 {
62 	static const VkFormat stencilFormats[] =
63 	{
64 		VK_FORMAT_S8_UINT,
65 		VK_FORMAT_D16_UNORM_S8_UINT,
66 		VK_FORMAT_D24_UNORM_S8_UINT,
67 		VK_FORMAT_D32_SFLOAT_S8_UINT,
68 	};
69 
70 	for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(stencilFormats); ++i)
71 	{
72 		VkFormatProperties formatProps;
73 		instanceInterface.getPhysicalDeviceFormatProperties(device, stencilFormats[i], &formatProps);
74 
75 		if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
76 		{
77 			return stencilFormats[i];
78 		}
79 	}
80 	TCU_FAIL("Cannot find supported stencil format");
81 }
82 
isFormatStencil(VkFormat format)83 bool isFormatStencil (VkFormat format)
84 {
85 	const auto textureFormat = vk::mapVkFormat(format);
86 	return (textureFormat.order == tcu::TextureFormat::DS || textureFormat.order == tcu::TextureFormat::S);
87 }
88 
89 class DiscardTestInstance : public DynamicStateBaseClass
90 {
91 public:
92 	DiscardTestInstance (Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, vk::VkFormat depthStencilFormat);
93 
94 	virtual void								initRenderPass	(const vk::VkDevice		device);
95 	virtual void								initFramebuffer	(const vk::VkDevice		device);
96 	virtual void								initPipeline	(const vk::VkDevice		device);
97 
98 	void										beginRenderPass	(const vk::VkClearColorValue& clearColor);
99 
100 	virtual tcu::TestStatus						iterate			(void);
101 
102 protected:
103 
setDynamicState(void)104 	virtual void								setDynamicState	(void) {
105 		DE_ASSERT(false);
106 	}
verifyResults(void)107 	virtual tcu::TestStatus						verifyResults	(void) {
108 		DE_ASSERT(false);
109 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "");
110 	}
111 	const vk::VkFormat					m_depthStencilAttachmentFormat;
112 
113 	de::SharedPtr<Draw::Image>			m_depthStencilImage;
114 	vk::Move<vk::VkImageView>			m_depthStencilView;
115 	std::vector<vk::VkDynamicState>		m_dynamicStates;
116 	VkBool32							m_depthBounds;
117 };
118 
DiscardTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName,vk::VkFormat depthStencilFormat)119 DiscardTestInstance::DiscardTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName, vk::VkFormat depthStencilFormat)
120 	: DynamicStateBaseClass(context, pipelineConstructionType, vertexShaderName, fragmentShaderName)
121 	, m_depthStencilAttachmentFormat(depthStencilFormat)
122 	, m_depthBounds(VK_FALSE)
123 {
124 	const vk::VkDevice				device					= m_context.getDevice();
125 
126 	const vk::VkExtent3D			stencilImageExtent		= { WIDTH, HEIGHT, 1 };
127 	const ImageCreateInfo			stencilImageCreateInfo	(vk::VK_IMAGE_TYPE_2D, m_depthStencilAttachmentFormat, stencilImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
128 
129 	m_depthStencilImage	= Image::createAndAlloc(m_vk, device, stencilImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
130 
131 	const ImageViewCreateInfo		stencilViewInfo(m_depthStencilImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_depthStencilAttachmentFormat);
132 	m_depthStencilView	= vk::createImageView(m_vk, device, &stencilViewInfo);
133 
134 	m_topology		= vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
135 
136 	m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
137 	m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
138 	m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
139 	m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
140 
141 	const vk::VkDescriptorSetLayoutBinding binding =
142 	{
143 		0u,
144 		vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
145 		1,
146 		vk::VK_SHADER_STAGE_FRAGMENT_BIT,
147 		DE_NULL
148 	};
149 
150 	DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo(1, &binding);
151 	m_otherSetLayout = vk::createDescriptorSetLayout(m_vk, device, &descriptorSetLayoutCreateInfo);
152 }
153 
initRenderPass(const vk::VkDevice device)154 void DiscardTestInstance::initRenderPass (const vk::VkDevice device)
155 {
156 	RenderPassCreateInfo renderPassCreateInfo;
157 	renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
158 		vk::VK_SAMPLE_COUNT_1_BIT,
159 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,
160 		vk::VK_ATTACHMENT_STORE_OP_STORE,
161 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
162 		vk::VK_ATTACHMENT_STORE_OP_STORE,
163 		vk::VK_IMAGE_LAYOUT_GENERAL,
164 		vk::VK_IMAGE_LAYOUT_GENERAL));
165 	renderPassCreateInfo.addAttachment(AttachmentDescription(m_depthStencilAttachmentFormat,
166 		vk::VK_SAMPLE_COUNT_1_BIT,
167 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,
168 		vk::VK_ATTACHMENT_STORE_OP_STORE,
169 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,
170 		vk::VK_ATTACHMENT_STORE_OP_STORE,
171 		vk::VK_IMAGE_LAYOUT_GENERAL,
172 		vk::VK_IMAGE_LAYOUT_GENERAL));
173 
174 	const vk::VkAttachmentReference colorAttachmentReference =
175 	{
176 		0,
177 		vk::VK_IMAGE_LAYOUT_GENERAL
178 	};
179 
180 	const vk::VkAttachmentReference stencilAttachmentReference =
181 	{
182 		1,
183 		vk::VK_IMAGE_LAYOUT_GENERAL
184 	};
185 
186 	renderPassCreateInfo.addSubpass(SubpassDescription(
187 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
188 		0,
189 		0,
190 		DE_NULL,
191 		1,
192 		&colorAttachmentReference,
193 		DE_NULL,
194 		stencilAttachmentReference,
195 		0,
196 		DE_NULL
197 	)
198 	);
199 
200 	m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
201 }
202 
initFramebuffer(const vk::VkDevice device)203 void DiscardTestInstance::initFramebuffer (const vk::VkDevice device)
204 {
205 	std::vector<vk::VkImageView> attachments(2);
206 	attachments[0] = *m_colorTargetView;
207 	attachments[1] = *m_depthStencilView;
208 
209 	const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
210 
211 	m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
212 }
213 
initPipeline(const vk::VkDevice device)214 void DiscardTestInstance::initPipeline(const vk::VkDevice device)
215 {
216 	const vk::Unique<vk::VkShaderModule>					vs(createShaderModule	(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
217 	const vk::Unique<vk::VkShaderModule>					fs(createShaderModule	(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
218 	std::vector<vk::VkViewport>								viewports				{ { 0.0f, 0.0f, (float)WIDTH, (float)HEIGHT, 0.0f, 1.0f } };
219 	std::vector<vk::VkRect2D>								scissors				{ { { 0u, 0u }, { WIDTH, HEIGHT } } };
220 
221 	const PipelineCreateInfo::ColorBlendState::Attachment	attachmentState;
222 	const PipelineCreateInfo::ColorBlendState				colorBlendState(1u, static_cast<const vk::VkPipelineColorBlendAttachmentState*>(&attachmentState));
223 	const PipelineCreateInfo::RasterizerState				rasterizerState;
224 	PipelineCreateInfo::DepthStencilState					depthStencilState;
225 	const PipelineCreateInfo::DynamicState					dynamicState(m_dynamicStates);
226 
227 	depthStencilState.depthTestEnable		= VK_TRUE;
228 	depthStencilState.depthWriteEnable		= VK_TRUE;
229 	depthStencilState.depthCompareOp		= VK_COMPARE_OP_ALWAYS;
230 	depthStencilState.depthBoundsTestEnable = m_depthBounds;
231 	depthStencilState.minDepthBounds		= 0.0f;
232 	depthStencilState.maxDepthBounds		= 1.0f;
233 	depthStencilState.stencilTestEnable		= VK_TRUE;
234 	depthStencilState.front.failOp			= VK_STENCIL_OP_KEEP;
235 	depthStencilState.front.passOp			= VK_STENCIL_OP_REPLACE;
236 	depthStencilState.front.depthFailOp		= VK_STENCIL_OP_KEEP;
237 	depthStencilState.front.compareOp		= VK_COMPARE_OP_ALWAYS;
238 	depthStencilState.front.compareMask		= 0u;
239 	depthStencilState.front.writeMask		= 0u;
240 	depthStencilState.front.reference		= 0u;
241 	depthStencilState.back.failOp			= VK_STENCIL_OP_KEEP;
242 	depthStencilState.back.passOp			= VK_STENCIL_OP_REPLACE;
243 	depthStencilState.back.depthFailOp		= VK_STENCIL_OP_KEEP;
244 	depthStencilState.back.compareOp		= VK_COMPARE_OP_ALWAYS;
245 	depthStencilState.back.compareMask		= 0u;
246 	depthStencilState.back.writeMask		= 0u;
247 	depthStencilState.back.reference		= 0u;
248 
249 	m_pipeline.setDefaultTopology(m_topology)
250 		.setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState))
251 		.setDefaultMultisampleState()
252 		.setupVertexInputState(&m_vertexInputState)
253 		.setupPreRasterizationShaderState(viewports,
254 			scissors,
255 			*m_pipelineLayout,
256 			*m_renderPass,
257 			0u,
258 			*vs,
259 			static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState))
260 		.setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState))
261 		.setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState))
262 		.setMonolithicPipelineLayout(*m_pipelineLayout)
263 		.buildPipeline();
264 }
265 
beginRenderPass(const vk::VkClearColorValue & clearColor)266 void DiscardTestInstance::beginRenderPass (const vk::VkClearColorValue& clearColor)
267 {
268 	beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
269 
270 	initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
271 		vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
272 
273 	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
274 	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
275 		vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
276 
277 	const vk::VkMemoryBarrier memBarrier =
278 	{
279 		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
280 		DE_NULL,
281 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
282 		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
283 	};
284 
285 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
286 		vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
287 		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
288 
289 	if (isFormatStencil(m_depthStencilAttachmentFormat)) {
290 		initialTransitionStencil2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
291 	}
292 	else
293 	{
294 		initialTransitionDepth2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
295 	}
296 
297 
298 	const vk::VkClearDepthStencilValue	depthStencilClearValue	= { 0.0f, 0 };
299 	const ImageSubresourceRange			subresourceRangeStencil = m_depthStencilAttachmentFormat == vk::VK_FORMAT_S8_UINT ? vk::VK_IMAGE_ASPECT_STENCIL_BIT : vk::VK_IMAGE_ASPECT_DEPTH_BIT;
300 	m_vk.cmdClearDepthStencilImage(*m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL, &depthStencilClearValue, 1, &subresourceRangeStencil);
301 
302 	vk::VkMemoryBarrier dsMemBarrier;
303 	dsMemBarrier.sType = vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER;
304 	dsMemBarrier.pNext = NULL;
305 	dsMemBarrier.srcAccessMask = vk::VK_ACCESS_TRANSFER_WRITE_BIT;
306 	dsMemBarrier.dstAccessMask = vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
307 
308 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 1, &dsMemBarrier, 0, NULL, 0, NULL);
309 
310 	vk::beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
311 }
iterate(void)312 tcu::TestStatus DiscardTestInstance::iterate(void) {
313 	const vk::VkQueue					queue				= m_context.getUniversalQueue();
314 	const vk::VkDevice					device				= m_context.getDevice();
315 	Allocator&							allocator			= m_context.getDefaultAllocator();
316 
317 	const VkDescriptorPoolSize			poolSizes[] =
318 	{
319 		{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,	1u	},
320 	};
321 	const VkDescriptorPoolCreateInfo	poolInfo =
322 	{
323 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
324 		DE_NULL,
325 		vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
326 		1u,		// maxSets
327 		DE_LENGTH_OF_ARRAY(poolSizes),
328 		poolSizes,
329 	};
330 
331 	vk::Move<vk::VkDescriptorPool>		descriptorPool		= createDescriptorPool(m_vk, device, &poolInfo);
332 	vk::Move<vk::VkDescriptorSet>		descriptorSet		= makeDescriptorSet(m_vk, device, *descriptorPool, *m_otherSetLayout);
333 
334 	const vk::VkDeviceSize				size				= sizeof(int);
335 
336 	const BufferWithMemory				buffer				(m_vk, device, allocator, makeBufferCreateInfo(size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT), MemoryRequirement::HostVisible);
337 
338 	deUint32*							ptr					= (deUint32*)buffer.getAllocation().getHostPtr();
339 	deMemset(ptr, 0u, static_cast<std::size_t>(size));
340 
341 	{
342 		const vk::VkDescriptorBufferInfo	bufferInfo		= makeDescriptorBufferInfo(*buffer, 0, size);
343 		const vk::VkWriteDescriptorSet		descriptorWrite =
344 		{
345 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
346 			DE_NULL,
347 			*descriptorSet,
348 			0u,		// dstBinding
349 			0u,		// dstArrayElement
350 			1u,		// descriptorCount
351 			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
352 			DE_NULL,
353 			&bufferInfo,
354 			DE_NULL,
355 		};
356 
357 		m_vk.updateDescriptorSets(device, 1, &descriptorWrite, 0u, DE_NULL);
358 	}
359 
360 	const vk::VkClearColorValue			clearColor			= { { 0.0f, 0.0f, 0.0f, 1.0f } };
361 	beginRenderPass(clearColor);
362 	m_vk.cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &*descriptorSet, 0, nullptr);
363 	m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.getPipeline());
364 	const vk::VkDeviceSize vertexBufferOffset = 0;
365 	const vk::VkBuffer		vertexBuffer = m_vertexBuffer->object();
366 	m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
367 
368 	setDynamicState();
369 
370 	m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
371 	endRenderPass(m_vk, *m_cmdBuffer);
372 	endCommandBuffer(m_vk, *m_cmdBuffer);
373 
374 	submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
375 
376 	return verifyResults();
377 }
378 
379 class StencilTestInstance : public DiscardTestInstance
380 {
381 public:
StencilTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)382 	StencilTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
383 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
384 	{
385 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, vk::VK_DYNAMIC_STATE_STENCIL_REFERENCE };
386 		const auto features = context.getDeviceFeatures();
387 		m_depthBounds = features.depthBounds;
388 
389 		DynamicStateBaseClass::initialize();
390 	}
391 
setDynamicState(void)392 	virtual void setDynamicState(void) {
393 		uint32_t value = 0x80;
394 		m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
395 		m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
396 		m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, value);
397 		m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
398 		m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
399 		m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, value);
400 	}
401 
verifyResults(void)402 	virtual tcu::TestStatus verifyResults(void) {
403 		const vk::VkQueue					queue			= m_context.getUniversalQueue();
404 		const vk::VkOffset3D				zeroOffset		= { 0, 0, 0 };
405 		tcu::ConstPixelBufferAccess			renderedFrame	= m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_STENCIL_BIT);
406 		de::SharedPtr<tcu::TextureLevel>	stencilFrame;
407 
408 		if (tcu::isCombinedDepthStencilType(renderedFrame.getFormat().type))
409 		{
410 			stencilFrame = de::SharedPtr<tcu::TextureLevel>( new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8), WIDTH, HEIGHT, 1u));
411 
412 			tcu::copy(stencilFrame->getAccess(), tcu::getEffectiveDepthStencilAccess(renderedFrame, tcu::Sampler::MODE_STENCIL));
413 			renderedFrame = stencilFrame->getAccess();
414 		}
415 
416 		for (int i = 0; i < WIDTH; ++i) {
417 			for (int j = 0; j < HEIGHT; ++j) {
418 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
419 				if (pixel[0] != 0.0f) {
420 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
421 				}
422 			}
423 		}
424 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
425 	}
426 };
427 
428 class ViewportTestInstance : public DiscardTestInstance
429 {
430 public:
ViewportTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)431 	ViewportTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
432 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
433 	{
434 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_VIEWPORT };
435 		DynamicStateBaseClass::initialize();
436 	}
437 
setDynamicState(void)438 	virtual void setDynamicState(void) {
439 		vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(WIDTH, HEIGHT));
440 		m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
441 	}
442 
verifyResults(void)443 	virtual tcu::TestStatus verifyResults(void) {
444 		const vk::VkQueue	queue = m_context.getUniversalQueue();
445 		tcu::Texture2D		referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
446 		referenceFrame.allocLevel(0);
447 
448 		const vk::VkOffset3D				zeroOffset = { 0, 0, 0 };
449 		const tcu::ConstPixelBufferAccess	renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
450 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
451 
452 		for (int i = 0; i < WIDTH; ++i) {
453 			for (int j = 0; j < HEIGHT; ++j) {
454 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
455 				if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
456 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
457 				}
458 			}
459 		}
460 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
461 	}
462 };
463 
464 class ScissorTestInstance : public DiscardTestInstance
465 {
466 public:
ScissorTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)467 	ScissorTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
468 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
469 	{
470 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_SCISSOR };
471 		DynamicStateBaseClass::initialize();
472 	}
473 
setDynamicState(void)474 	virtual void setDynamicState(void) {
475 		vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(WIDTH, HEIGHT));
476 		m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
477 	}
478 
verifyResults(void)479 	virtual tcu::TestStatus verifyResults(void) {
480 		const vk::VkQueue	queue = m_context.getUniversalQueue();
481 		tcu::Texture2D		referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
482 		referenceFrame.allocLevel(0);
483 
484 		const vk::VkOffset3D				zeroOffset = { 0, 0, 0 };
485 		const tcu::ConstPixelBufferAccess	renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
486 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
487 
488 		for (int i = 0; i < WIDTH; ++i) {
489 			for (int j = 0; j < HEIGHT; ++j) {
490 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
491 				if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
492 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
493 				}
494 			}
495 		}
496 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
497 	}
498 };
499 
500 class DepthTestInstance : public DiscardTestInstance
501 {
502 public:
DepthTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)503 	DepthTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
504 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, vk::VK_FORMAT_D32_SFLOAT)
505 	{
506 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_DEPTH_BIAS, vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS };
507 		DynamicStateBaseClass::initialize();
508 	}
509 
setDynamicState(void)510 	virtual void setDynamicState(void) {
511 		m_vk.cmdSetDepthBounds(*m_cmdBuffer, 0.0f, 1.0f);
512 		m_vk.cmdSetDepthBias(*m_cmdBuffer, 1.0f, 1.0f, 1.0f);
513 	}
514 
verifyResults(void)515 	virtual tcu::TestStatus verifyResults(void) {
516 		const vk::VkQueue					queue			= m_context.getUniversalQueue();
517 		const vk::VkOffset3D				zeroOffset		= { 0, 0, 0 };
518 		const tcu::ConstPixelBufferAccess	renderedFrame	= m_depthStencilImage->readSurface(queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_DEPTH_BIT);
519 
520 		for (int i = 0; i < WIDTH; ++i) {
521 			for (int j = 0; j < HEIGHT; ++j) {
522 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
523 				if (pixel[0] != 0.0f) {
524 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
525 				}
526 			}
527 		}
528 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
529 	}
530 };
531 
532 class BlendTestInstance : public DiscardTestInstance
533 {
534 public:
BlendTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)535 	BlendTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
536 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
537 	{
538 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_BLEND_CONSTANTS };
539 		DynamicStateBaseClass::initialize();
540 	}
541 
setDynamicState(void)542 	virtual void setDynamicState(void) {
543 		float blendConstantsants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
544 		m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
545 	}
546 
verifyResults(void)547 	virtual tcu::TestStatus verifyResults(void) {
548 		const vk::VkQueue	queue = m_context.getUniversalQueue();
549 		tcu::Texture2D		referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
550 		referenceFrame.allocLevel(0);
551 
552 		const vk::VkOffset3D				zeroOffset = { 0, 0, 0 };
553 		const tcu::ConstPixelBufferAccess	renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
554 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
555 
556 		for (int i = 0; i < WIDTH; ++i) {
557 			for (int j = 0; j < HEIGHT; ++j) {
558 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
559 				if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
560 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
561 				}
562 			}
563 		}
564 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
565 	}
566 };
567 
568 class LineTestInstance : public DiscardTestInstance
569 {
570 public:
LineTestInstance(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName)571 	LineTestInstance(Context& context, vk::PipelineConstructionType pipelineConstructionType, const char* vertexShaderName, const char* fragmentShaderName)
572 		: DiscardTestInstance(context, pipelineConstructionType, vertexShaderName, fragmentShaderName, pickSupportedStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice()))
573 	{
574 		m_dynamicStates = { vk::VK_DYNAMIC_STATE_LINE_WIDTH };
575 		DynamicStateBaseClass::initialize();
576 	}
577 
setDynamicState(void)578 	virtual void setDynamicState(void) {
579 		m_vk.cmdSetLineWidth(*m_cmdBuffer, 1.0f);
580 	}
581 
verifyResults(void)582 	virtual tcu::TestStatus verifyResults(void) {
583 		const vk::VkQueue	queue = m_context.getUniversalQueue();
584 		tcu::Texture2D		referenceFrame(vk::mapVkFormat(m_depthStencilAttachmentFormat), WIDTH, HEIGHT);
585 		referenceFrame.allocLevel(0);
586 
587 		const vk::VkOffset3D				zeroOffset = { 0, 0, 0 };
588 		const tcu::ConstPixelBufferAccess	renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
589 			vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
590 
591 		for (int i = 0; i < WIDTH; ++i) {
592 			for (int j = 0; j < HEIGHT; ++j) {
593 				const tcu::Vec4 pixel = renderedFrame.getPixel(i, j);
594 				if (pixel != tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) {
595 					return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
596 				}
597 			}
598 		}
599 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
600 	}
601 };
602 
603 class DiscardTestCase : public vkt::TestCase
604 {
605 public:
DiscardTestCase(tcu::TestContext & context,const char * name,const char * description,vk::PipelineConstructionType pipelineConstructionType,TestDynamicStateDiscard testCase)606 	DiscardTestCase (tcu::TestContext& context, const char* name, const char* description, vk::PipelineConstructionType pipelineConstructionType, TestDynamicStateDiscard testCase)
607 		: TestCase	(context, name, description)
608 		, m_pipelineConstructionType(pipelineConstructionType)
609 		, m_testCase(testCase)
610 		, m_depthBounds(false)
611 	{
612 	}
613 
checkSupport(Context & context) const614 	virtual void	checkSupport(Context& context) const
615 	{
616 		checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
617 	}
618 
createInstance(Context & context) const619 	TestInstance* createInstance(Context& context) const
620 	{
621 		switch (m_testCase) {
622 		case TEST_STENCIL:
623 			return new StencilTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
624 		case TEST_VIEWPORT:
625 			return new ViewportTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
626 		case TEST_SCISSOR:
627 			return new ScissorTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
628 		case TEST_DEPTH:
629 			return new DepthTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
630 		case TEST_BLEND_CONSTANTS:
631 			return new BlendTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
632 		case TEST_LINE_WIDTH:
633 			return new LineTestInstance(context, m_pipelineConstructionType, "discard.vert", "discard.frag");
634 		default:
635 			break;
636 		}
637 		DE_ASSERT(false);
638 		return nullptr;
639 	}
640 
initPrograms(vk::SourceCollections & programCollection) const641 	virtual void initPrograms(vk::SourceCollections& programCollection) const
642 	{
643 		std::ostringstream vert;
644 		vert
645 			<< "#version 450\n"
646 			<< "\n"
647 			<< "layout(location = 0) in vec4 in_position;"
648 			<< "layout(location = 1) in vec4 in_color;"
649 			<< "\n"
650 			<< "layout(location = 0) out vec4 out_color;"
651 			<< "out gl_PerVertex { vec4 gl_Position; };"
652 			<< "\n"
653 			<< "void main ()\n"
654 			<< "{\n"
655 			<< "	gl_Position = in_position;\n"
656 			<< "	out_color = in_color;\n"
657 			<< "}\n";
658 
659 		programCollection.glslSources.add("discard.vert") << glu::VertexSource(vert.str());
660 
661 		std::ostringstream frag;
662 		frag
663 			<< "#version 450\n"
664 			<< "\n"
665 			<< "layout (set=0, binding=0, std140) uniform InputBlock {\n"
666 			<< "	int discard_all;\n"
667 			<< "} unif;\n"
668 			<< "\n"
669 			<< "layout (location = 0) in vec4 in_color;"
670 			<< "\n"
671 			<< "layout (location = 0) out vec4 color;"
672 			<< "\n"
673 			<< "void main ()\n"
674 			<< "{\n"
675 			<< "	if (unif.discard_all == 0) {\n"
676 			<< "		discard;\n"
677 			<< "	}\n"
678 			<< "	color = in_color;\n"
679 			<< "}\n";
680 
681 		programCollection.glslSources.add("discard.frag") << glu::FragmentSource(frag.str());
682 	}
683 
684 protected:
685 	vk::PipelineConstructionType	m_pipelineConstructionType;
686 	TestDynamicStateDiscard			m_testCase;
687 	VkBool32						m_depthBounds;
688 };
689 
DynamicStateDiscardTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)690 DynamicStateDiscardTests::DynamicStateDiscardTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
691 	: TestCaseGroup					(testCtx, "discard", "Tests for dynamic state")
692 	, m_pipelineConstructionType	(pipelineConstructionType)
693 {
694 	/* Left blank on purpose */
695 }
696 
~DynamicStateDiscardTests()697 DynamicStateDiscardTests::~DynamicStateDiscardTests ()
698 {
699 }
700 
init(void)701 void DynamicStateDiscardTests::init (void)
702 {
703 	addChild(new DiscardTestCase(m_testCtx, "stencil", "Use dynamic stencil with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_STENCIL));
704 	addChild(new DiscardTestCase(m_testCtx, "viewport", "Use dynamic viewport with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_VIEWPORT));
705 	addChild(new DiscardTestCase(m_testCtx, "scissor", "Use dynamic scissor with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_SCISSOR));
706 	addChild(new DiscardTestCase(m_testCtx, "depth", "Use dynamic depth with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_DEPTH));
707 	addChild(new DiscardTestCase(m_testCtx, "blend", "Use dynamic blend constants with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_BLEND_CONSTANTS));
708 	addChild(new DiscardTestCase(m_testCtx, "line", "Use dynamic line width with discard", m_pipelineConstructionType, TestDynamicStateDiscard::TEST_LINE_WIDTH));
709 }
710 
711 } // DynamicState
712 } // vkt
713