1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel 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 Dynamic Raster State Tests
23 *//*--------------------------------------------------------------------*/
24
25#include "vktDynamicStateRSTests.hpp"
26
27#include "vktDynamicStateBaseClass.hpp"
28#include "vktDynamicStateTestCaseUtil.hpp"
29
30#include "vkImageUtil.hpp"
31
32#include "tcuTextureUtil.hpp"
33#include "tcuImageCompare.hpp"
34#include "tcuRGBA.hpp"
35
36#include "deMath.h"
37
38namespace vkt
39{
40namespace DynamicState
41{
42namespace
43{
44
45class DepthBiasBaseCase : public TestInstance
46{
47public:
48	DepthBiasBaseCase (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
49		: TestInstance						(context)
50		, m_colorAttachmentFormat			(vk::VK_FORMAT_R8G8B8A8_UNORM)
51		, m_topology						(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
52		, m_vk								(context.getDeviceInterface())
53		, m_vertexShaderName				(vertexShaderName)
54		, m_fragmentShaderName				(fragmentShaderName)
55	{
56	}
57
58protected:
59
60	enum
61	{
62		WIDTH	= 128,
63		HEIGHT	= 128
64	};
65
66	vk::VkFormat									m_colorAttachmentFormat;
67	vk::VkFormat									m_depthStencilAttachmentFormat;
68
69	vk::VkPrimitiveTopology							m_topology;
70
71	const vk::DeviceInterface&						m_vk;
72
73	vk::Move<vk::VkPipeline>						m_pipeline;
74	vk::Move<vk::VkPipelineLayout>					m_pipelineLayout;
75
76	de::SharedPtr<Image>							m_colorTargetImage;
77	vk::Move<vk::VkImageView>						m_colorTargetView;
78
79	de::SharedPtr<Image>							m_depthStencilImage;
80	vk::Move<vk::VkImageView>						m_attachmentView;
81
82	PipelineCreateInfo::VertexInputState			m_vertexInputState;
83	de::SharedPtr<Buffer>							m_vertexBuffer;
84
85	vk::Move<vk::VkCommandPool>						m_cmdPool;
86	vk::Move<vk::VkCommandBuffer>					m_cmdBuffer;
87
88	vk::Move<vk::VkFramebuffer>						m_framebuffer;
89	vk::Move<vk::VkRenderPass>						m_renderPass;
90
91	std::string										m_vertexShaderName;
92	std::string										m_fragmentShaderName;
93
94	std::vector<PositionColorVertex>				m_data;
95
96	PipelineCreateInfo::DepthStencilState			m_depthStencilState;
97
98	void initialize (void)
99	{
100		const vk::VkDevice device	= m_context.getDevice();
101
102		vk::VkFormatProperties formatProperties;
103		// check for VK_FORMAT_D24_UNORM_S8_UINT support
104		m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), vk::VK_FORMAT_D24_UNORM_S8_UINT, &formatProperties);
105		if (formatProperties.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
106		{
107			m_depthStencilAttachmentFormat = vk::VK_FORMAT_D24_UNORM_S8_UINT;
108		}
109		else
110		{
111			// check for VK_FORMAT_D32_SFLOAT_S8_UINT support
112			m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), vk::VK_FORMAT_D32_SFLOAT_S8_UINT, &formatProperties);
113			if (formatProperties.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
114			{
115				m_depthStencilAttachmentFormat = vk::VK_FORMAT_D32_SFLOAT_S8_UINT;
116			}
117			else
118				throw tcu::NotSupportedError("No valid depth stencil attachment available");
119		}
120
121		const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
122		m_pipelineLayout			= vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
123
124		const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
125		const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
126
127		const vk::VkExtent3D imageExtent = { WIDTH, HEIGHT, 1 };
128		ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
129											  vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
130
131		m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
132
133		const ImageCreateInfo depthStencilImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_depthStencilAttachmentFormat, imageExtent,
134														  1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
135														  vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
136
137		m_depthStencilImage = Image::createAndAlloc(m_vk, device, depthStencilImageCreateInfo, m_context.getDefaultAllocator());
138
139		const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
140		m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
141
142		const ImageViewCreateInfo attachmentViewInfo(m_depthStencilImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_depthStencilAttachmentFormat);
143		m_attachmentView = vk::createImageView(m_vk, device, &attachmentViewInfo);
144
145		RenderPassCreateInfo renderPassCreateInfo;
146		renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
147																 vk::VK_SAMPLE_COUNT_1_BIT,
148																 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
149																 vk::VK_ATTACHMENT_STORE_OP_STORE,
150																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
151																 vk::VK_ATTACHMENT_STORE_OP_STORE,
152																 vk::VK_IMAGE_LAYOUT_GENERAL,
153																 vk::VK_IMAGE_LAYOUT_GENERAL));
154
155		renderPassCreateInfo.addAttachment(AttachmentDescription(m_depthStencilAttachmentFormat,
156																 vk::VK_SAMPLE_COUNT_1_BIT,
157																 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
158																 vk::VK_ATTACHMENT_STORE_OP_STORE,
159																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
160																 vk::VK_ATTACHMENT_STORE_OP_STORE,
161																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
162																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));
163
164		const vk::VkAttachmentReference colorAttachmentReference =
165		{
166			0,
167			vk::VK_IMAGE_LAYOUT_GENERAL
168		};
169
170		const vk::VkAttachmentReference depthAttachmentReference =
171		{
172			1,
173			vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
174		};
175
176		renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
177														   0,
178														   0,
179														   DE_NULL,
180														   1,
181														   &colorAttachmentReference,
182														   DE_NULL,
183														   depthAttachmentReference,
184														   0,
185														   DE_NULL));
186
187		m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
188
189		const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
190		{
191			0,
192			(deUint32)sizeof(tcu::Vec4) * 2,
193			vk::VK_VERTEX_INPUT_RATE_VERTEX,
194		};
195
196		const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
197		{
198			{
199				0u,
200				0u,
201				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
202				0u
203			},
204			{
205				1u,
206				0u,
207				vk::VK_FORMAT_R32G32B32A32_SFLOAT,
208				(deUint32)(sizeof(float)* 4),
209			}
210		};
211
212		m_vertexInputState = PipelineCreateInfo::VertexInputState(1,
213																  &vertexInputBindingDescription,
214																  2,
215																  vertexInputAttributeDescriptions);
216
217		const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
218
219		PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
220		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
221		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
222		pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
223		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_topology));
224		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
225		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1));
226		pipelineCreateInfo.addState(m_depthStencilState);
227		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
228		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
229		pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState());
230
231		m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
232
233		std::vector<vk::VkImageView> attachments(2);
234		attachments[0] = *m_colorTargetView;
235		attachments[1] = *m_attachmentView;
236
237		const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
238
239		m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
240
241		const vk::VkDeviceSize dataSize = m_data.size() * sizeof(PositionColorVertex);
242		m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize,
243			vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
244			m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
245
246		deUint8* ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr());
247		deMemcpy(ptr, &m_data[0], static_cast<size_t>(dataSize));
248
249		vk::flushMappedMemoryRange(m_vk, device,
250								   m_vertexBuffer->getBoundMemory().getMemory(),
251								   m_vertexBuffer->getBoundMemory().getOffset(),
252								   sizeof(dataSize));
253
254		const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex());
255		m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
256
257		const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
258		{
259			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
260			DE_NULL,											// const void*				pNext;
261			*m_cmdPool,											// VkCommandPool			commandPool;
262			vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
263			1u,													// deUint32					bufferCount;
264		};
265		m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
266	}
267
268	virtual tcu::TestStatus iterate (void)
269	{
270		DE_ASSERT(false);
271		return tcu::TestStatus::fail("Should reimplement iterate() method");
272	}
273
274	void beginRenderPass (void)
275	{
276		const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
277		beginRenderPassWithClearColor(clearColor);
278	}
279
280	void beginRenderPassWithClearColor (const vk::VkClearColorValue &clearColor)
281	{
282		const CmdBufferBeginInfo beginInfo;
283		m_vk.beginCommandBuffer(*m_cmdBuffer, &beginInfo);
284
285		initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL);
286		initialTransitionDepthStencil2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
287
288		const ImageSubresourceRange subresourceRangeImage(vk::VK_IMAGE_ASPECT_COLOR_BIT);
289		m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
290								vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRangeImage);
291
292		const vk::VkClearDepthStencilValue depthStencilClearValue = { 0.0f, 0 };
293
294		const ImageSubresourceRange subresourceRangeDepthStencil[2] = { vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_ASPECT_STENCIL_BIT };
295
296		m_vk.cmdClearDepthStencilImage(*m_cmdBuffer, m_depthStencilImage->object(),
297									   vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &depthStencilClearValue, 2, subresourceRangeDepthStencil);
298
299		const vk::VkMemoryBarrier memBarrier =
300		{
301			vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
302			DE_NULL,
303			vk::VK_ACCESS_TRANSFER_WRITE_BIT,
304			vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
305				vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
306		};
307
308		m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
309			vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
310			vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
311			0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
312
313		const vk::VkRect2D renderArea = { { 0, 0 }, { WIDTH, HEIGHT } };
314		const RenderPassBeginInfo renderPassBegin(*m_renderPass, *m_framebuffer, renderArea);
315
316		transition2DImage(m_vk, *m_cmdBuffer, m_depthStencilImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
317
318		m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
319	}
320
321	void setDynamicViewportState (const deUint32 width, const deUint32 height)
322	{
323		vk::VkViewport viewport;
324		viewport.x = 0;
325		viewport.y = 0;
326		viewport.width = static_cast<float>(width);
327		viewport.height = static_cast<float>(height);
328		viewport.minDepth = 0.0f;
329		viewport.maxDepth = 1.0f;
330
331		m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
332
333		vk::VkRect2D scissor;
334		scissor.offset.x = 0;
335		scissor.offset.y = 0;
336		scissor.extent.width = width;
337		scissor.extent.height = height;
338		m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
339	}
340
341	void setDynamicViewportState (const deUint32 viewportCount, const vk::VkViewport* pViewports, const vk::VkRect2D* pScissors)
342	{
343		m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports);
344		m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors);
345	}
346
347	void setDynamicRasterizationState (const float lineWidth = 1.0f,
348		const float depthBiasConstantFactor = 0.0f,
349		const float depthBiasClamp = 0.0f,
350		const float depthBiasSlopeFactor = 0.0f)
351	{
352		m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth);
353		m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
354	}
355
356	void setDynamicBlendState (const float const1 = 0.0f, const float const2 = 0.0f,
357		const float const3 = 0.0f, const float const4 = 0.0f)
358	{
359		float blendConstantsants[4] = { const1, const2, const3, const4 };
360		m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
361	}
362
363	void setDynamicDepthStencilState (const float minDepthBounds = -1.0f, const float maxDepthBounds = 1.0f,
364		const deUint32 stencilFrontCompareMask = 0xffffffffu, const deUint32 stencilFrontWriteMask = 0xffffffffu,
365		const deUint32 stencilFrontReference = 0, const deUint32 stencilBackCompareMask = 0xffffffffu,
366		const deUint32 stencilBackWriteMask = 0xffffffffu, const deUint32 stencilBackReference = 0)
367	{
368		m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds);
369		m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask);
370		m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask);
371		m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference);
372		m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask);
373		m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask);
374		m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference);
375	}
376};
377
378class DepthBiasParamTestInstance : public DepthBiasBaseCase
379{
380public:
381	DepthBiasParamTestInstance (Context& context, ShaderMap shaders)
382		: DepthBiasBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
383	{
384		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), tcu::RGBA::blue().toVec()));
385		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 0.5f, 1.0f), tcu::RGBA::blue().toVec()));
386		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f), tcu::RGBA::blue().toVec()));
387		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f), tcu::RGBA::blue().toVec()));
388
389		m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
390		m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, 0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
391		m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
392		m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, -0.5f, 1.0f, 1.0f), tcu::RGBA::green().toVec()));
393
394		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), tcu::RGBA::red().toVec()));
395		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 0.5f, 1.0f), tcu::RGBA::red().toVec()));
396		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 0.5f, 1.0f), tcu::RGBA::red().toVec()));
397		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f), tcu::RGBA::red().toVec()));
398
399		// enable depth test
400		m_depthStencilState = PipelineCreateInfo::DepthStencilState(
401			vk::VK_TRUE, vk::VK_TRUE, vk::VK_COMPARE_OP_GREATER_OR_EQUAL);
402
403		DepthBiasBaseCase::initialize();
404	}
405
406	virtual tcu::TestStatus iterate (void)
407	{
408		tcu::TestLog &log		= m_context.getTestContext().getLog();
409		const vk::VkQueue queue = m_context.getUniversalQueue();
410
411		beginRenderPass();
412
413		// set states here
414		setDynamicViewportState(WIDTH, HEIGHT);
415		setDynamicBlendState();
416		setDynamicDepthStencilState();
417
418		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
419
420		const vk::VkDeviceSize vertexBufferOffset	= 0;
421		const vk::VkBuffer vertexBuffer				= m_vertexBuffer->object();
422		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
423
424		setDynamicRasterizationState(1.0f, 0.0f);
425		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
426		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 4, 0);
427
428		setDynamicRasterizationState(1.0f, -1.0f);
429		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 8, 0);
430
431		m_vk.cmdEndRenderPass(*m_cmdBuffer);
432		m_vk.endCommandBuffer(*m_cmdBuffer);
433
434		vk::VkSubmitInfo submitInfo =
435		{
436			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
437			DE_NULL,							// const void*				pNext;
438			0,									// deUint32					waitSemaphoreCount;
439			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
440			(const vk::VkPipelineStageFlags*)DE_NULL,
441			1,									// deUint32					commandBufferCount;
442			&m_cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
443			0,									// deUint32					signalSemaphoreCount;
444			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
445		};
446		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
447
448		// validation
449		{
450			VK_CHECK(m_vk.queueWaitIdle(queue));
451
452			tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
453			referenceFrame.allocLevel(0);
454
455			const deInt32 frameWidth = referenceFrame.getWidth();
456			const deInt32 frameHeight = referenceFrame.getHeight();
457
458			tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
459
460			for (int y = 0; y < frameHeight; y++)
461			{
462				const float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
463
464				for (int x = 0; x < frameWidth; x++)
465				{
466					const float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
467
468					if (xCoord >= -0.5f && xCoord <= 0.5f && yCoord >= -0.5f && yCoord <= 0.5f)
469						referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
470					else
471						referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
472				}
473			}
474
475			const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
476			const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
477				vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
478
479			if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
480				referenceFrame.getLevel(0), renderedFrame, 0.05f,
481				tcu::COMPARE_LOG_RESULT))
482			{
483				return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
484			}
485
486			return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
487		}
488	}
489};
490
491class DepthBiasClampParamTestInstance : public DepthBiasBaseCase
492{
493public:
494	DepthBiasClampParamTestInstance (Context& context, ShaderMap shaders)
495		: DepthBiasBaseCase (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
496	{
497		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::blue().toVec()));
498		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::RGBA::blue().toVec()));
499		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::blue().toVec()));
500		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::RGBA::blue().toVec()));
501
502		m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, 0.5f, 0.01f, 1.0f), tcu::RGBA::green().toVec()));
503		m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, 0.5f, 0.01f, 1.0f), tcu::RGBA::green().toVec()));
504		m_data.push_back(PositionColorVertex(tcu::Vec4(-0.5f, -0.5f, 0.01f, 1.0f), tcu::RGBA::green().toVec()));
505		m_data.push_back(PositionColorVertex(tcu::Vec4(0.5f, -0.5f, 0.01f, 1.0f), tcu::RGBA::green().toVec()));
506
507		// enable depth test
508		m_depthStencilState = PipelineCreateInfo::DepthStencilState(vk::VK_TRUE, vk::VK_TRUE, vk::VK_COMPARE_OP_GREATER_OR_EQUAL);
509
510		DepthBiasBaseCase::initialize();
511	}
512
513	virtual tcu::TestStatus iterate (void)
514	{
515		tcu::TestLog &log = m_context.getTestContext().getLog();
516		const vk::VkQueue queue = m_context.getUniversalQueue();
517
518		beginRenderPass();
519
520		// set states here
521		setDynamicViewportState(WIDTH, HEIGHT);
522		setDynamicBlendState();
523		setDynamicDepthStencilState();
524
525		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
526
527		const vk::VkDeviceSize vertexBufferOffset = 0;
528		const vk::VkBuffer vertexBuffer = m_vertexBuffer->object();
529		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
530
531		setDynamicRasterizationState(1.0f, 1000.0f, 0.005f);
532		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
533
534		setDynamicRasterizationState(1.0f, 0.0f);
535		m_vk.cmdDraw(*m_cmdBuffer, 4, 1, 4, 0);
536
537		m_vk.cmdEndRenderPass(*m_cmdBuffer);
538		m_vk.endCommandBuffer(*m_cmdBuffer);
539
540		vk::VkSubmitInfo submitInfo =
541		{
542			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
543			DE_NULL,							// const void*				pNext;
544			0,									// deUint32					waitSemaphoreCount;
545			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
546			(const vk::VkPipelineStageFlags*)DE_NULL,
547			1,									// deUint32					commandBufferCount;
548			&m_cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
549			0,									// deUint32					signalSemaphoreCount;
550			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
551		};
552		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
553
554		// validation
555		{
556			VK_CHECK(m_vk.queueWaitIdle(queue));
557
558			tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
559			referenceFrame.allocLevel(0);
560
561			const deInt32 frameWidth	= referenceFrame.getWidth();
562			const deInt32 frameHeight	= referenceFrame.getHeight();
563
564			tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
565
566			for (int y = 0; y < frameHeight; y++)
567			{
568				float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
569
570				for (int x = 0; x < frameWidth; x++)
571				{
572					float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
573
574					if (xCoord >= -0.5f && xCoord <= 0.5f && yCoord >= -0.5f && yCoord <= 0.5f)
575						referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
576					else
577						referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
578				}
579			}
580
581			const vk::VkOffset3D zeroOffset					= { 0, 0, 0 };
582			const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
583				vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, vk::VK_IMAGE_ASPECT_COLOR_BIT);
584
585			if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
586				referenceFrame.getLevel(0), renderedFrame, 0.05f,
587				tcu::COMPARE_LOG_RESULT))
588			{
589				return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
590			}
591
592			return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
593		}
594	}
595};
596
597class LineWidthParamTestInstance : public DynamicStateBaseClass
598{
599public:
600	LineWidthParamTestInstance (Context& context, ShaderMap shaders)
601		: DynamicStateBaseClass (context, shaders[glu::SHADERTYPE_VERTEX], shaders[glu::SHADERTYPE_FRAGMENT])
602	{
603		// Check if line width test is supported
604		{
605			const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
606
607			if (!deviceFeatures.wideLines)
608				throw tcu::NotSupportedError("Line width test is unsupported");
609		}
610
611		m_topology = vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
612
613		m_data.push_back(PositionColorVertex(tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f), tcu::RGBA::green().toVec()));
614		m_data.push_back(PositionColorVertex(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), tcu::RGBA::green().toVec()));
615
616		DynamicStateBaseClass::initialize();
617	}
618
619	virtual tcu::TestStatus iterate (void)
620	{
621		tcu::TestLog &log		= m_context.getTestContext().getLog();
622		const vk::VkQueue queue = m_context.getUniversalQueue();
623
624		beginRenderPass();
625
626		// set states here
627		vk::VkPhysicalDeviceProperties deviceProperties;
628		m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &deviceProperties);
629
630		setDynamicViewportState(WIDTH, HEIGHT);
631		setDynamicBlendState();
632		setDynamicDepthStencilState();
633		setDynamicRasterizationState(deFloatFloor(deviceProperties.limits.lineWidthRange[1]));
634
635		m_vk.cmdBindPipeline(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
636
637		const vk::VkDeviceSize vertexBufferOffset	= 0;
638		const vk::VkBuffer vertexBuffer				= m_vertexBuffer->object();
639		m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
640
641		m_vk.cmdDraw(*m_cmdBuffer, static_cast<deUint32>(m_data.size()), 1, 0, 0);
642
643		m_vk.cmdEndRenderPass(*m_cmdBuffer);
644		m_vk.endCommandBuffer(*m_cmdBuffer);
645
646		vk::VkSubmitInfo submitInfo =
647		{
648			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
649			DE_NULL,							// const void*				pNext;
650			0,									// deUint32					waitSemaphoreCount;
651			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
652			(const vk::VkPipelineStageFlags*)DE_NULL,
653			1,									// deUint32					commandBufferCount;
654			&m_cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
655			0,									// deUint32					signalSemaphoreCount;
656			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
657		};
658		m_vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
659
660		// validation
661		{
662			VK_CHECK(m_vk.queueWaitIdle(queue));
663
664			tcu::Texture2D referenceFrame(vk::mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
665			referenceFrame.allocLevel(0);
666
667			const deInt32 frameWidth = referenceFrame.getWidth();
668			const deInt32 frameHeight = referenceFrame.getHeight();
669
670			tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
671
672			for (int y = 0; y < frameHeight; y++)
673			{
674				float yCoord = (float)(y / (0.5*frameHeight)) - 1.0f;
675
676				for (int x = 0; x < frameWidth; x++)
677				{
678					float xCoord = (float)(x / (0.5*frameWidth)) - 1.0f;
679					float lineHalfWidth = (float)(deFloor(deviceProperties.limits.lineWidthRange[1]) / frameHeight);
680
681					if (xCoord >= -1.0f && xCoord <= 1.0f && yCoord >= -lineHalfWidth && yCoord <= lineHalfWidth)
682						referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), x, y);
683				}
684			}
685
686			const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
687			const tcu::ConstPixelBufferAccess renderedFrame = m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(),
688																							  vk::VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT,
689																							  vk::VK_IMAGE_ASPECT_COLOR_BIT);
690
691			if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
692				referenceFrame.getLevel(0), renderedFrame, 0.05f,
693				tcu::COMPARE_LOG_RESULT))
694			{
695				return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Image verification failed");
696			}
697
698			return tcu::TestStatus(QP_TEST_RESULT_PASS, "Image verification passed");
699		}
700	}
701};
702
703} //anonymous
704
705DynamicStateRSTests::DynamicStateRSTests (tcu::TestContext& testCtx)
706	: TestCaseGroup (testCtx, "rs_state", "Tests for rasterizer state")
707{
708	/* Left blank on purpose */
709}
710
711DynamicStateRSTests::~DynamicStateRSTests ()
712{
713}
714
715void DynamicStateRSTests::init (void)
716{
717	ShaderMap shaderPaths;
718	shaderPaths[glu::SHADERTYPE_VERTEX]		= "vulkan/dynamic_state/VertexFetch.vert";
719	shaderPaths[glu::SHADERTYPE_FRAGMENT]	= "vulkan/dynamic_state/VertexFetch.frag";
720
721	addChild(new InstanceFactory<DepthBiasParamTestInstance>(m_testCtx, "depth_bias", "Test depth bias functionality", shaderPaths));
722	addChild(new InstanceFactory<DepthBiasClampParamTestInstance>(m_testCtx, "depth_bias_clamp", "Test depth bias clamp functionality", shaderPaths));
723	addChild(new InstanceFactory<LineWidthParamTestInstance>(m_testCtx, "line_width", "Draw a line with width set to max defined by physical device", shaderPaths));
724}
725
726} // DynamicState
727} // vkt
728