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 State Tests - Base Class
23 *//*--------------------------------------------------------------------*/
24
25#include "vktDynamicStateBaseClass.hpp"
26
27#include "vkPrograms.hpp"
28
29namespace vkt
30{
31namespace DynamicState
32{
33
34using namespace Draw;
35
36DynamicStateBaseClass::DynamicStateBaseClass (Context& context, const char* vertexShaderName, const char* fragmentShaderName)
37	: TestInstance				(context)
38	, m_colorAttachmentFormat   (vk::VK_FORMAT_R8G8B8A8_UNORM)
39	, m_topology				(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
40	, m_vk						(context.getDeviceInterface())
41	, m_vertexShaderName		(vertexShaderName)
42	, m_fragmentShaderName		(fragmentShaderName)
43{
44}
45
46void DynamicStateBaseClass::initialize (void)
47{
48	const vk::VkDevice device		= m_context.getDevice();
49	const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
50
51	const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
52	m_pipelineLayout = vk::createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo);
53
54	const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
55	const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
56												vk::VK_IMAGE_TILING_OPTIMAL, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
57
58	m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator());
59
60	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
61	m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
62
63	RenderPassCreateInfo renderPassCreateInfo;
64	renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
65															 vk::VK_SAMPLE_COUNT_1_BIT,
66															 vk::VK_ATTACHMENT_LOAD_OP_LOAD,
67															 vk::VK_ATTACHMENT_STORE_OP_STORE,
68															 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
69															 vk::VK_ATTACHMENT_STORE_OP_STORE,
70															 vk::VK_IMAGE_LAYOUT_GENERAL,
71															 vk::VK_IMAGE_LAYOUT_GENERAL));
72
73	const vk::VkAttachmentReference colorAttachmentReference =
74	{
75		0,
76		vk::VK_IMAGE_LAYOUT_GENERAL
77	};
78
79	renderPassCreateInfo.addSubpass(SubpassDescription(
80		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
81		0,
82		0,
83		DE_NULL,
84		1,
85		&colorAttachmentReference,
86		DE_NULL,
87		AttachmentReference(),
88		0,
89		DE_NULL
90		)
91		);
92
93	m_renderPass = vk::createRenderPass(m_vk, device, &renderPassCreateInfo);
94
95	std::vector<vk::VkImageView> colorAttachments(1);
96	colorAttachments[0] = *m_colorTargetView;
97
98	const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
99
100	m_framebuffer = vk::createFramebuffer(m_vk, device, &framebufferCreateInfo);
101
102	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
103	{
104		0,
105		(deUint32)sizeof(tcu::Vec4) * 2,
106		vk::VK_VERTEX_INPUT_RATE_VERTEX,
107	};
108
109	const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
110	{
111		{
112			0u,
113			0u,
114			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
115			0u
116		},
117		{
118			1u,
119			0u,
120			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
121			(deUint32)(sizeof(float)* 4),
122		}
123	};
124
125	m_vertexInputState = PipelineCreateInfo::VertexInputState(
126		1,
127		&vertexInputBindingDescription,
128		2,
129		vertexInputAttributeDescriptions);
130
131	const vk::VkDeviceSize dataSize = m_data.size() * sizeof(PositionColorVertex);
132	m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
133											m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
134
135	deUint8* ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr());
136	deMemcpy(ptr, &m_data[0], (size_t)dataSize);
137
138	vk::flushMappedMemoryRange(m_vk, device,
139		m_vertexBuffer->getBoundMemory().getMemory(),
140		m_vertexBuffer->getBoundMemory().getOffset(),
141		dataSize);
142
143	const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
144	m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
145
146	const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
147	{
148		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
149		DE_NULL,											// const void*				pNext;
150		*m_cmdPool,											// VkCommandPool			commandPool;
151		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
152		1u,													// deUint32					bufferCount;
153	};
154	m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
155
156	initPipeline(device);
157}
158
159void DynamicStateBaseClass::initPipeline (const vk::VkDevice device)
160{
161	const vk::Unique<vk::VkShaderModule> vs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_vertexShaderName), 0));
162	const vk::Unique<vk::VkShaderModule> fs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get(m_fragmentShaderName), 0));
163
164	const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
165
166	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
167	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
168	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
169	pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(m_vertexInputState));
170	pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(m_topology));
171	pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
172	pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1));
173	pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
174	pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
175	pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
176	pipelineCreateInfo.addState(PipelineCreateInfo::DynamicState());
177
178	m_pipeline = vk::createGraphicsPipeline(m_vk, device, DE_NULL, &pipelineCreateInfo);
179}
180
181tcu::TestStatus DynamicStateBaseClass::iterate (void)
182{
183	DE_ASSERT(false);
184	return tcu::TestStatus::fail("Implement iterate() method!");
185}
186
187void DynamicStateBaseClass::beginRenderPass (void)
188{
189	const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
190	beginRenderPassWithClearColor(clearColor);
191}
192
193void DynamicStateBaseClass::beginRenderPassWithClearColor (const vk::VkClearColorValue& clearColor)
194{
195	const CmdBufferBeginInfo beginInfo;
196	m_vk.beginCommandBuffer(*m_cmdBuffer, &beginInfo);
197
198	initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL);
199
200	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
201	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
202		vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
203
204	const vk::VkMemoryBarrier memBarrier =
205	{
206		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
207		DE_NULL,
208		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
209		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
210	};
211
212	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
213		vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
214		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
215
216	const vk::VkRect2D renderArea = { { 0, 0 }, { WIDTH, HEIGHT } };
217	const RenderPassBeginInfo renderPassBegin(*m_renderPass, *m_framebuffer, renderArea);
218
219	m_vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
220}
221
222void DynamicStateBaseClass::setDynamicViewportState (const deUint32 width, const deUint32 height)
223{
224	vk::VkViewport viewport;
225	viewport.x = 0;
226	viewport.y = 0;
227	viewport.width = static_cast<float>(width);
228	viewport.height = static_cast<float>(height);
229	viewport.minDepth = 0.0f;
230	viewport.maxDepth = 1.0f;
231
232	m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
233
234	vk::VkRect2D scissor;
235	scissor.offset.x = 0;
236	scissor.offset.y = 0;
237	scissor.extent.width = width;
238	scissor.extent.height = height;
239	m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
240}
241
242void DynamicStateBaseClass::setDynamicViewportState (deUint32 viewportCount, const vk::VkViewport* pViewports, const vk::VkRect2D* pScissors)
243{
244	m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports);
245	m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors);
246}
247
248void DynamicStateBaseClass::setDynamicRasterizationState (const float lineWidth,
249														 const float depthBiasConstantFactor,
250														 const float depthBiasClamp,
251														 const float depthBiasSlopeFactor)
252{
253	m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth);
254	m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
255}
256
257void DynamicStateBaseClass::setDynamicBlendState (const float const1, const float const2, const float const3, const float const4)
258{
259	float blendConstantsants[4] = { const1, const2, const3, const4 };
260	m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
261}
262
263void DynamicStateBaseClass::setDynamicDepthStencilState (const float	minDepthBounds,
264														 const float	maxDepthBounds,
265														 const deUint32 stencilFrontCompareMask,
266														 const deUint32 stencilFrontWriteMask,
267														 const deUint32 stencilFrontReference,
268														 const deUint32 stencilBackCompareMask,
269														 const deUint32 stencilBackWriteMask,
270														 const deUint32 stencilBackReference)
271{
272	m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds);
273	m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask);
274	m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask);
275	m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference);
276	m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask);
277	m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask);
278	m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference);
279}
280
281} // DynamicState
282} // vkt
283