1afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski/*------------------------------------------------------------------------
2afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * Vulkan Conformance Tests
3afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * ------------------------
4afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *
5afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * Copyright (c) 2016 The Khronos Group Inc.
6afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *
7afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * Licensed under the Apache License, Version 2.0 (the "License");
8afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * you may not use this file except in compliance with the License.
9afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * You may obtain a copy of the License at
10afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *
11afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *      http://www.apache.org/licenses/LICENSE-2.0
12afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *
13afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * Unless required by applicable law or agreed to in writing, software
14afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * distributed under the License is distributed on an "AS IS" BASIS,
15afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * See the License for the specific language governing permissions and
17afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * limitations under the License.
18afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *
19afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *//*!
20afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * \file
21afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski * \brief Negative viewport height (part of VK_KHR_maintenance1)
22afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski *//*--------------------------------------------------------------------*/
23afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
24afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktDrawNegativeViewportHeightTests.hpp"
25afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktDrawCreateInfoUtil.hpp"
26afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktDrawImageObjectUtil.hpp"
27afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktDrawBufferObjectUtil.hpp"
28afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktTestGroupUtil.hpp"
29afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vktTestCaseUtil.hpp"
30afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
31afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vkPrograms.hpp"
32afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vkTypeUtil.hpp"
33afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "vkImageUtil.hpp"
34afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
35afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "tcuVector.hpp"
36afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "tcuTextureUtil.hpp"
37afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "tcuImageCompare.hpp"
38afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
39afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski#include "deSharedPtr.hpp"
40afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
41afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskinamespace vkt
42afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
43afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskinamespace Draw
44afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
45afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskinamespace
46afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
47afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiusing namespace vk;
48afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiusing tcu::Vec4;
49afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiusing de::SharedPtr;
50afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiusing de::MovePtr;
51afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
52afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskienum Constants
53afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
54afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	WIDTH	= 256,
55afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	HEIGHT	= WIDTH/2,
56afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski};
57afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
58afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskistruct TestParams
59afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
60afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	VkFrontFace				frontFace;
61afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	VkCullModeFlagBits		cullMode;
62afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski};
63afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
64afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiclass NegativeViewportHeightTestInstance : public TestInstance
65afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
66afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskipublic:
67afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski									NegativeViewportHeightTestInstance	(Context& context, const TestParams& params);
68afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	tcu::TestStatus					iterate								(void);
69afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	tcu::ConstPixelBufferAccess		draw								(const VkViewport viewport);
70afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	MovePtr<tcu::TextureLevel>		generateReferenceImage				(void) const;
71afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	bool							isCulled							(const VkFrontFace triangleFace) const;
72afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
73afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiprivate:
74afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const TestParams				m_params;
75afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkFormat					m_colorAttachmentFormat;
76afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	SharedPtr<Image>				m_colorTargetImage;
77afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	Move<VkImageView>				m_colorTargetView;
78afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	SharedPtr<Buffer>				m_vertexBuffer;
79afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	Move<VkRenderPass>				m_renderPass;
80afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	Move<VkFramebuffer>				m_framebuffer;
81afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	Move<VkPipelineLayout>			m_pipelineLayout;
82afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	Move<VkPipeline>				m_pipeline;
83afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski};
84afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
85afc1695f999fddc0db14cb626ad6aefbcd330311Maciej JesionowskiNegativeViewportHeightTestInstance::NegativeViewportHeightTestInstance (Context& context, const TestParams& params)
86afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	: TestInstance				(context)
87afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	, m_params					(params)
88afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	, m_colorAttachmentFormat	(VK_FORMAT_R8G8B8A8_UNORM)
89afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
90afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const DeviceInterface&	vk		= m_context.getDeviceInterface();
91afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkDevice			device	= m_context.getDevice();
92afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
93afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Vertex data
94afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
95afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		std::vector<Vec4> vertexData;
96afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
97afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		// CCW triangle
98afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4(-0.8f, -0.6f, 0.0f, 1.0f));	//  0-----2
99afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4(-0.8f,  0.6f, 0.0f, 1.0f));	//   |  /
100afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4(-0.2f, -0.6f, 0.0f, 1.0f));	//  1|/
101afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
102afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		// CW triangle
103afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4( 0.2f, -0.6f, 0.0f, 1.0f));	//  0-----1
104afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4( 0.8f, -0.6f, 0.0f, 1.0f));	//    \  |
105afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vertexData.push_back(Vec4( 0.8f,  0.6f, 0.0f, 1.0f));	//      \|2
106afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
107afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkDeviceSize dataSize = vertexData.size() * sizeof(Vec4);
108afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
109afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski												m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
110afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
111afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), &vertexData[0], static_cast<std::size_t>(dataSize));
112afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
113afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
114afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
115afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Render pass
116afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
117afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkExtent3D		targetImageExtent		= { WIDTH, HEIGHT, 1 };
118afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkImageUsageFlags	targetImageUsageFlags	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
119afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
120afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const ImageCreateInfo	targetImageCreateInfo(
121afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_IMAGE_TYPE_2D,						// imageType,
122afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			m_colorAttachmentFormat,				// format,
123afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			targetImageExtent,						// extent,
124afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			1u,										// mipLevels,
125afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			1u,										// arrayLayers,
126afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_SAMPLE_COUNT_1_BIT,					// samples,
127afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_IMAGE_TILING_OPTIMAL,				// tiling,
128afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			targetImageUsageFlags);					// usage,
129afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
130afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
131afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
132afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		RenderPassCreateInfo	renderPassCreateInfo;
133afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		renderPassCreateInfo.addAttachment(AttachmentDescription(
134afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			m_colorAttachmentFormat,				// format
135afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_SAMPLE_COUNT_1_BIT,					// samples
136afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ATTACHMENT_LOAD_OP_LOAD,				// loadOp
137afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ATTACHMENT_STORE_OP_STORE,			// storeOp
138afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ATTACHMENT_LOAD_OP_DONT_CARE,		// stencilLoadOp
139afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ATTACHMENT_STORE_OP_DONT_CARE,		// stencilStoreOp
140afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_IMAGE_LAYOUT_GENERAL,				// initialLayout
141afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_IMAGE_LAYOUT_GENERAL));				// finalLayout
142afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
143afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkAttachmentReference colorAttachmentReference =
144afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
145afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			0u,
146afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_IMAGE_LAYOUT_GENERAL
147afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		};
148afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
149afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		renderPassCreateInfo.addSubpass(SubpassDescription(
150afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_PIPELINE_BIND_POINT_GRAPHICS,		// pipelineBindPoint
151afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			(VkSubpassDescriptionFlags)0,			// flags
152afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			0u,										// inputAttachmentCount
153afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,								// inputAttachments
154afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			1u,										// colorAttachmentCount
155afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			&colorAttachmentReference,				// colorAttachments
156afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,								// resolveAttachments
157afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			AttachmentReference(),					// depthStencilAttachment
158afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			0u,										// preserveAttachmentCount
159afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL));								// preserveAttachments
160afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
161afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
162afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
163afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
164afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Framebuffer
165afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
166afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const ImageViewCreateInfo colorTargetViewInfo (m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
167afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
168afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
169afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		std::vector<VkImageView> colorAttachments(1);
170afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		colorAttachments[0] = *m_colorTargetView;
171afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
172afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const FramebufferCreateInfo	framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
173afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
174afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
175afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
176afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Vertex input
177afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
178afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkVertexInputBindingDescription		vertexInputBindingDescription =
179afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
180afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0u,										// uint32_t             binding;
181afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		sizeof(Vec4),							// uint32_t             stride;
182afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate    inputRate;
183afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
184afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
185afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
186afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
187afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0u,										// uint32_t    location;
188afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0u,										// uint32_t    binding;
189afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat    format;
190afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0u										// uint32_t    offset;
191afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
192afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
193afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const PipelineCreateInfo::VertexInputState	vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
194afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski																										1, &vertexInputAttributeDescription);
195afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
196afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Graphics pipeline
197afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
198afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkRect2D scissor =
199afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
200afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ 0,		0		},		// x, y
201afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ WIDTH,	HEIGHT	},		// width, height
202afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
203afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
204afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	std::vector<VkDynamicState>		dynamicStates;
205afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
206afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
207afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Unique<VkShaderModule>	vertexModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
208afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Unique<VkShaderModule>	fragmentModule	(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
209afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
210afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const PipelineLayoutCreateInfo	pipelineLayoutCreateInfo;
211afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
212afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
213afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const PipelineCreateInfo::ColorBlendState::Attachment colorBlendAttachmentState;
214afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
215afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
216afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,   "main", VK_SHADER_STAGE_VERTEX_BIT));
217afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
218afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
219afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
220afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState	(1, &colorBlendAttachmentState));
221afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(1, std::vector<VkViewport>(), std::vector<VkRect2D>(1, scissor)));
222afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	());
223afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	(
224afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_FALSE,					// depthClampEnable
225afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_FALSE,					// rasterizerDiscardEnable
226afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_POLYGON_MODE_FILL,		// polygonMode
227afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_params.cullMode,			// cullMode
228afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		m_params.frontFace,			// frontFace
229afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_FALSE,					// depthBiasEnable
230afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0.0f,						// depthBiasConstantFactor
231afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0.0f,						// depthBiasClamp
232afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0.0f,						// depthBiasSlopeFactor
233afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		1.0f));						// lineWidth
234afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
235afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	pipelineCreateInfo.addState (PipelineCreateInfo::DynamicState		(dynamicStates));
236afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
237afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
238afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
239afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
240afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskitcu::ConstPixelBufferAccess NegativeViewportHeightTestInstance::draw (const VkViewport viewport)
241afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
242afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const DeviceInterface&	vk					= m_context.getDeviceInterface();
243afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkDevice			device				= m_context.getDevice();
244afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkQueue			queue				= m_context.getUniversalQueue();
245afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
246afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
247afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Command buffer
248afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
249afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const CmdPoolCreateInfo		cmdPoolCreateInfo	(queueFamilyIndex);
250afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Unique<VkCommandPool>	cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
251afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
252afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
253afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
254afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType			sType;
255afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		DE_NULL,											// const void*				pNext;
256afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		*cmdPool,											// VkCommandPool			commandPool;
257afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel		level;
258afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		1u,													// deUint32					bufferCount;
259afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
260afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
261afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
262afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Draw
263afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
264afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
265afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const CmdBufferBeginInfo beginInfo;
266afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
267afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
268afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
269afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport);
270afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
271afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
272afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkClearColorValue		clearColor			= makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f).color;
273afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const ImageSubresourceRange subresourceRange	(VK_IMAGE_ASPECT_COLOR_BIT);
274afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
275afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		initialTransitionColor2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL);
276afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vk.cmdClearColorImage(*cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
277afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
278afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
279afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkMemoryBarrier memBarrier =
280afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
281afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_STRUCTURE_TYPE_MEMORY_BARRIER,												// VkStructureType    sType;
282afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,																		// const void*        pNext;
283afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ACCESS_TRANSFER_WRITE_BIT,													// VkAccessFlags      srcAccessMask;
284afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT		// VkAccessFlags      dstAccessMask;
285afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		};
286afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
287afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
288afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
289afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
290afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkRect2D				renderArea		= { { 0, 0 }, { WIDTH, HEIGHT } };
291afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const RenderPassBeginInfo	renderPassBegin	(*m_renderPass, *m_framebuffer, renderArea);
292afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
293afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, VK_SUBPASS_CONTENTS_INLINE);
294afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
295afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
296afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkDeviceSize	offset	= 0;
297afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkBuffer		buffer	= m_vertexBuffer->object();
298afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
299afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &offset);
300afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
301afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
302afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
303afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	vk.cmdDraw(*cmdBuffer, 6, 1, 0, 0);
304afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	vk.cmdEndRenderPass(*cmdBuffer);
305afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	vk.endCommandBuffer(*cmdBuffer);
306afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
307afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Submit
308afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
309afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkFenceCreateInfo fenceInfo	=
310afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
311afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,		// VkStructureType       sType;
312afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,									// const void*           pNext;
313afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			(VkFenceCreateFlags)0,						// VkFenceCreateFlags    flags;
314afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		};
315afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const Unique<VkFence>	fence		(createFence(vk, device, &fenceInfo));
316afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkSubmitInfo		submitInfo	=
317afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
318afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			VK_STRUCTURE_TYPE_SUBMIT_INFO,				// VkStructureType                sType;
319afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,									// const void*                    pNext;
320afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			0,											// uint32_t                       waitSemaphoreCount;
321afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL,									// const VkSemaphore*             pWaitSemaphores;
322afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			(const VkPipelineStageFlags*)DE_NULL,		// const VkPipelineStageFlags*    pWaitDstStageMask;
323afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			1,											// uint32_t                       commandBufferCount;
324afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			&cmdBuffer.get(),							// const VkCommandBuffer*         pCommandBuffers;
325afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			0,											// uint32_t                       signalSemaphoreCount;
326afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_NULL										// const VkSemaphore*             pSignalSemaphores;
327afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		};
328afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
329afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
330afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), VK_TRUE, ~0ull));
331afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
332afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
333afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Get result
334afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
335afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const VkOffset3D zeroOffset = { 0, 0, 0 };
336afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
337afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
338afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
339afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
340afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski//! Determine if a triangle with triangleFace orientation will be culled or not
341afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskibool NegativeViewportHeightTestInstance::isCulled (const VkFrontFace triangleFace) const
342afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
343afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const bool isFrontFacing = (triangleFace == m_params.frontFace);
344afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
345afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (m_params.cullMode == VK_CULL_MODE_FRONT_BIT && isFrontFacing)
346afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return true;
347afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (m_params.cullMode == VK_CULL_MODE_BACK_BIT  && !isFrontFacing)
348afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return true;
349afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
350afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	return m_params.cullMode == VK_CULL_MODE_FRONT_AND_BACK;
351afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
352afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
353afc1695f999fddc0db14cb626ad6aefbcd330311Maciej JesionowskiMovePtr<tcu::TextureLevel> NegativeViewportHeightTestInstance::generateReferenceImage (void) const
354afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
355afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	DE_ASSERT(HEIGHT == WIDTH/2);
356afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
357afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	MovePtr<tcu::TextureLevel>		image	(new tcu::TextureLevel(mapVkFormat(m_colorAttachmentFormat), WIDTH, HEIGHT));
358afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const tcu::PixelBufferAccess	access	(image->getAccess());
359afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Vec4						black	(0.0f, 0.0f, 0.0f, 1.0f);
360afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Vec4						white	(1.0f);
361afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const Vec4						gray	(0.5f, 0.5f, 0.5f, 1.0f);
362afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
363afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	tcu::clear(access, black);
364afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
365afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const int p1 =      static_cast<int>(static_cast<float>(HEIGHT) * (1.0f - 0.6f) / 2.0f);
366afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const int p2 = p1 + static_cast<int>(static_cast<float>(HEIGHT) * (2.0f * 0.6f) / 2.0f);
367afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
368afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// left triangle (CCW -> CW after y-flip)
369afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (!isCulled(VK_FRONT_FACE_CLOCKWISE))
370afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
371afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const Vec4& color = (m_params.frontFace == VK_FRONT_FACE_CLOCKWISE ? white : gray);
372afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
373afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		for (int y = p1; y <= p2; ++y)
374afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		for (int x = p1; x <  y;  ++x)
375afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			access.setPixel(color, x, y);
376afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
377afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
378afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// right triangle (CW -> CCW after y-flip)
379afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (!isCulled(VK_FRONT_FACE_COUNTER_CLOCKWISE))
380afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
381afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const Vec4& color = (m_params.frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE ? white : gray);
382afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
383afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		for (int y = p1;        y <= p2;          ++y)
384afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		for (int x = WIDTH - y; x <  p2 + HEIGHT; ++x)
385afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			access.setPixel(color, x, y);
386afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
387afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
388afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	return image;
389afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
390afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
391afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskistd::string getCullModeStr (const VkCullModeFlagBits cullMode)
392afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
393afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Cull mode flags are a bit special, because there's a meaning to 0 and or'ed flags.
394afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// The function getCullModeFlagsStr() doesn't work too well in this case.
395afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
396afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	switch (cullMode)
397afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
398afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		case VK_CULL_MODE_NONE:				return "VK_CULL_MODE_NONE";
399afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		case VK_CULL_MODE_FRONT_BIT:		return "VK_CULL_MODE_FRONT_BIT";
400afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		case VK_CULL_MODE_BACK_BIT:			return "VK_CULL_MODE_BACK_BIT";
401afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		case VK_CULL_MODE_FRONT_AND_BACK:	return "VK_CULL_MODE_FRONT_AND_BACK";
402afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
403afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		default:
404afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			DE_ASSERT(0);
405afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			return std::string();
406afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
407afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
408afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
409afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskitcu::TestStatus NegativeViewportHeightTestInstance::iterate (void)
410afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
411afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Check requirements
412afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
413afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), std::string("VK_KHR_maintenance1")))
414afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_maintenance1");
415afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
416afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Set up the viewport and draw
417afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
418afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const VkViewport viewport =
419afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
420afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0.0f,							// float    x;
421afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		static_cast<float>(HEIGHT),		// float    y;
422afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		static_cast<float>(WIDTH),		// float    width;
423afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		-static_cast<float>(HEIGHT),	// float    height;
424afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		0.0f,							// float    minDepth;
425afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		1.0f,							// float    maxDepth;
426afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
427afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
428afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const tcu::ConstPixelBufferAccess	resultImage	= draw(viewport);
429afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
430afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	// Verify the results
431afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
432afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	tcu::TestLog&				log				= m_context.getTestContext().getLog();
433afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	MovePtr<tcu::TextureLevel>	referenceImage	= generateReferenceImage();
434afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
435afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	log << tcu::TestLog::Message
436afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< "Drawing two triangles with negative viewport height, which will cause a y-flip. This changes the sign of the triangle's area."
437afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< tcu::TestLog::EndMessage;
438afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	log << tcu::TestLog::Message
439afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< "After the flip, the triangle on the left is CW and the triangle on the right is CCW. Right angles of the both triangles should be at the bottom of the image."
440afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< " Front face is white, back face is gray."
441afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< tcu::TestLog::EndMessage;
442afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	log << tcu::TestLog::Message
443afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< "Front face: " << getFrontFaceName(m_params.frontFace) << "\n"
444afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< "Cull mode: "  << getCullModeStr  (m_params.cullMode)  << "\n"
445afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		<< tcu::TestLog::EndMessage;
446afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
447afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	if (!tcu::fuzzyCompare(log, "Image compare", "Image compare", referenceImage->getAccess(), resultImage, 0.02f, tcu::COMPARE_LOG_RESULT))
448afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return tcu::TestStatus::fail("Rendered image is incorrect");
449afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	else
450afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return tcu::TestStatus::pass("Pass");
451afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
452afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
453afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiclass NegativeViewportHeightTest : public TestCase
454afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
455afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskipublic:
456afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	NegativeViewportHeightTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
457afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		: TestCase	(testCtx, name, description)
458afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		, m_params	(params)
459afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
460afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
461afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
462afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	void initPrograms (SourceCollections& programCollection) const
463afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
464afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		// Vertex shader
465afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
466afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			std::ostringstream src;
467afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
468afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "\n"
469afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "layout(location = 0) in vec4 in_position;\n"
470afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "\n"
471afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "out gl_PerVertex {\n"
472afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "    vec4  gl_Position;\n"
473afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "};\n"
474afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "\n"
475afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "void main(void)\n"
476afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "{\n"
477afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "    gl_Position = in_position;\n"
478afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "}\n";
479afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
480afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
481afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		}
482afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
483afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		// Fragment shader
484afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
485afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			std::ostringstream src;
486afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
487afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "\n"
488afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "layout(location = 0) out vec4 out_color;\n"
489afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "\n"
490afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "void main(void)\n"
491afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "{\n"
492afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "    if (gl_FrontFacing)\n"
493afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "        out_color = vec4(1.0);\n"
494afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "    else\n"
495afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "        out_color = vec4(vec3(0.5), 1.0);\n"
496afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski				<< "}\n";
497afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
498afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
499afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		}
500afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
501afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
502afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	virtual TestInstance* createInstance (Context& context) const
503afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
504afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		return new NegativeViewportHeightTestInstance(context, m_params);
505afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
506afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
507afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskiprivate:
508afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const TestParams	m_params;
509afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski};
510afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
511afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskivoid populateTestGroup (tcu::TestCaseGroup* testGroup)
512afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
513afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const struct
514afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
515afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const char* const	name;
516afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VkFrontFace			frontFace;
517afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	} frontFace[] =
518afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
519afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "front_ccw",	VK_FRONT_FACE_COUNTER_CLOCKWISE	},
520afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "front_cw",	VK_FRONT_FACE_CLOCKWISE			},
521afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
522afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
523afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	const struct
524afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
525afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const char* const	name;
526afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		VkCullModeFlagBits	cullMode;
527afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	} cullMode[] =
528afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
529afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "cull_none",	VK_CULL_MODE_NONE			},
530afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "cull_front",	VK_CULL_MODE_FRONT_BIT		},
531afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "cull_back",	VK_CULL_MODE_BACK_BIT		},
532afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{ "cull_both",	VK_CULL_MODE_FRONT_AND_BACK	},
533afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	};
534afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
535afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	for (int ndxFrontFace = 0; ndxFrontFace < DE_LENGTH_OF_ARRAY(frontFace); ++ndxFrontFace)
536afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	for (int ndxCullMode  = 0; ndxCullMode  < DE_LENGTH_OF_ARRAY(cullMode);  ++ndxCullMode)
537afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	{
538afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		const TestParams params =
539afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		{
540afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			frontFace[ndxFrontFace].frontFace,
541afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski			cullMode[ndxCullMode].cullMode,
542afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		};
543afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		std::ostringstream	name;
544afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		name << frontFace[ndxFrontFace].name << "_" << cullMode[ndxCullMode].name;
545afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
546afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski		testGroup->addChild(new NegativeViewportHeightTest(testGroup->getTestContext(), name.str(), "", params));
547afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	}
548afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
549afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
550afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}	// anonymous
551afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
552afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowskitcu::TestCaseGroup*	createNegativeViewportHeightTests (tcu::TestContext& testCtx)
553afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski{
554afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski	return createTestGroup(testCtx, "negative_viewport_height", "Negative viewport height (VK_KHR_maintenance1)", populateTestGroup);
555afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}
556afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski
557afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}	// Draw
558afc1695f999fddc0db14cb626ad6aefbcd330311Maciej Jesionowski}	// vkt
559