• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Intel Corporation
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Dynamic State Tests - Base Class
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktDynamicStateBaseClass.hpp"
28 
29 #include "vkPrograms.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkBarrierUtil.hpp"
35 
36 namespace vkt
37 {
38 namespace DynamicState
39 {
40 
41 using namespace Draw;
42 
DynamicStateBaseClass(Context & context,vk::PipelineConstructionType pipelineConstructionType,const char * vertexShaderName,const char * fragmentShaderName,const char * meshShaderName)43 DynamicStateBaseClass::DynamicStateBaseClass (Context& context,
44 											  vk::PipelineConstructionType pipelineConstructionType,
45 											  const char* vertexShaderName,
46 											  const char* fragmentShaderName,
47 											  const char* meshShaderName)
48 	: TestInstance					(context)
49 	, m_pipelineConstructionType	(pipelineConstructionType)
50 	, m_colorAttachmentFormat		(vk::VK_FORMAT_R8G8B8A8_UNORM)
51 	, m_topology					(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
52 	, m_vk							(context.getDeviceInterface())
53 	, m_pipeline					(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
54 	, m_vertexShaderName			(vertexShaderName ? vertexShaderName : "")
55 	, m_fragmentShaderName			(fragmentShaderName)
56 	, m_meshShaderName				(meshShaderName ? meshShaderName : "")
57 	, m_isMesh						(meshShaderName != nullptr)
58 {
59 	// We must provide either the mesh shader or the vertex shader.
60 	DE_ASSERT(static_cast<bool>(vertexShaderName) != static_cast<bool>(meshShaderName));
61 }
62 
initialize(void)63 void DynamicStateBaseClass::initialize (void)
64 {
65 	const vk::VkDevice						device				= m_context.getDevice();
66 	const deUint32							queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
67 	const auto								vertDescType		= (m_isMesh ? vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER : vk::VK_DESCRIPTOR_TYPE_MAX_ENUM);
68 	std::vector<vk::VkPushConstantRange>	pcRanges;
69 
70 	// The mesh shading pipeline will contain a set with vertex data.
71 #ifndef CTS_USES_VULKANSC
72 	if (m_isMesh)
73 	{
74 		vk::DescriptorSetLayoutBuilder	setLayoutBuilder;
75 		vk::DescriptorPoolBuilder		poolBuilder;
76 
77 		setLayoutBuilder.addSingleBinding(vertDescType, vk::VK_SHADER_STAGE_MESH_BIT_EXT);
78 		m_meshSetLayout = setLayoutBuilder.build(m_vk, device);
79 
80 		poolBuilder.addType(vertDescType);
81 		m_descriptorPool = poolBuilder.build(m_vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
82 
83 		m_descriptorSet = vk::makeDescriptorSet(m_vk, device, m_descriptorPool.get(), m_meshSetLayout.get());
84 		pcRanges.push_back(vk::makePushConstantRange(vk::VK_SHADER_STAGE_MESH_BIT_EXT, 0u, static_cast<uint32_t>(sizeof(uint32_t))));
85 	}
86 #endif // CTS_USES_VULKANSC
87 
88 	std::vector<vk::VkDescriptorSetLayout> rawSetLayouts;
89 
90 	if (m_meshSetLayout)
91 		rawSetLayouts.push_back(m_meshSetLayout.get());
92 
93 	if (m_otherSetLayout)
94 		rawSetLayouts.push_back(m_otherSetLayout.get());
95 
96 	m_pipelineLayout = vk::PipelineLayoutWrapper(m_pipelineConstructionType, m_vk, device, de::sizeU32(rawSetLayouts), de::dataOrNull(rawSetLayouts), de::sizeU32(pcRanges), de::dataOrNull(pcRanges));
97 
98 	const vk::VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
99 	const ImageCreateInfo targetImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, targetImageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT,
100 												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);
101 
102 	m_colorTargetImage = Image::createAndAlloc(m_vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
103 
104 	const ImageViewCreateInfo colorTargetViewInfo(m_colorTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
105 	m_colorTargetView = vk::createImageView(m_vk, device, &colorTargetViewInfo);
106 
107 	const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
108 	{
109 		0,
110 		(deUint32)sizeof(tcu::Vec4) * 2,
111 		vk::VK_VERTEX_INPUT_RATE_VERTEX,
112 	};
113 
114 	const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
115 	{
116 		{
117 			0u,
118 			0u,
119 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
120 			0u
121 		},
122 		{
123 			1u,
124 			0u,
125 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,
126 			(deUint32)(sizeof(float)* 4),
127 		}
128 	};
129 
130 	m_vertexInputState = PipelineCreateInfo::VertexInputState(
131 		1,
132 		&vertexInputBindingDescription,
133 		2,
134 		vertexInputAttributeDescriptions);
135 
136 	const vk::VkDeviceSize			dataSize	= de::dataSize(m_data);
137 	const vk::VkBufferUsageFlags	bufferUsage	= (m_isMesh ? vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
138 	m_vertexBuffer = Buffer::createAndAlloc(m_vk, device, BufferCreateInfo(dataSize, bufferUsage),
139 											m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
140 
141 	deUint8* ptr = reinterpret_cast<unsigned char *>(m_vertexBuffer->getBoundMemory().getHostPtr());
142 	deMemcpy(ptr, &m_data[0], (size_t)dataSize);
143 
144 	vk::flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
145 
146 	// Update descriptor set for mesh shaders.
147 	if (m_isMesh)
148 	{
149 		vk::DescriptorSetUpdateBuilder	updateBuilder;
150 		const auto						location		= vk::DescriptorSetUpdateBuilder::Location::binding(0u);
151 		const auto						bufferInfo		= vk::makeDescriptorBufferInfo(m_vertexBuffer->object(), 0ull, dataSize);
152 
153 		updateBuilder.writeSingle(m_descriptorSet.get(), location, vertDescType, &bufferInfo);
154 		updateBuilder.update(m_vk, device);
155 	}
156 
157 	const CmdPoolCreateInfo cmdPoolCreateInfo(queueFamilyIndex);
158 	m_cmdPool = vk::createCommandPool(m_vk, device, &cmdPoolCreateInfo);
159 
160 	const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
161 	{
162 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
163 		DE_NULL,											// const void*				pNext;
164 		*m_cmdPool,											// VkCommandPool			commandPool;
165 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
166 		1u,													// deUint32					bufferCount;
167 	};
168 	m_cmdBuffer = vk::allocateCommandBuffer(m_vk, device, &cmdBufferAllocateInfo);
169 
170 	initRenderPass(device);
171 	initFramebuffer(device);
172 	initPipeline(device);
173 }
174 
175 
initRenderPass(const vk::VkDevice device)176 void DynamicStateBaseClass::initRenderPass (const vk::VkDevice device)
177 {
178 	RenderPassCreateInfo renderPassCreateInfo;
179 	renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,
180 		vk::VK_SAMPLE_COUNT_1_BIT,
181 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,
182 		vk::VK_ATTACHMENT_STORE_OP_STORE,
183 		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
184 		vk::VK_ATTACHMENT_STORE_OP_STORE,
185 		vk::VK_IMAGE_LAYOUT_GENERAL,
186 		vk::VK_IMAGE_LAYOUT_GENERAL));
187 
188 	const vk::VkAttachmentReference colorAttachmentReference =
189 	{
190 		0,
191 		vk::VK_IMAGE_LAYOUT_GENERAL
192 	};
193 
194 	renderPassCreateInfo.addSubpass(SubpassDescription(
195 		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
196 		0,
197 		0,
198 		DE_NULL,
199 		1,
200 		&colorAttachmentReference,
201 		DE_NULL,
202 		AttachmentReference(),
203 		0,
204 		DE_NULL
205 	)
206 	);
207 
208 	m_renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, m_vk, device, &renderPassCreateInfo);
209 }
210 
initFramebuffer(const vk::VkDevice device)211 void DynamicStateBaseClass::initFramebuffer (const vk::VkDevice device)
212 {
213 	std::vector<vk::VkImageView> colorAttachments(1);
214 	colorAttachments[0] = *m_colorTargetView;
215 
216 	const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
217 
218 	m_renderPass.createFramebuffer(m_vk, device, &framebufferCreateInfo, m_colorTargetImage->object());
219 }
220 
initPipeline(const vk::VkDevice device)221 void DynamicStateBaseClass::initPipeline (const vk::VkDevice device)
222 {
223 	const PipelineCreateInfo::ColorBlendState				colorBlendState(1, &m_attachmentState);
224 	const PipelineCreateInfo::RasterizerState				rasterizerState;
225 	const PipelineCreateInfo::DepthStencilState             depthStencilState;
226 	const PipelineCreateInfo::DynamicState					dynamicState;
227 	const PipelineCreateInfo::MultiSampleState				multisampleState;
228 
229 	const auto&							binaries	= m_context.getBinaryCollection();
230 	const vk::ShaderWrapper				ms			(m_isMesh ? vk::ShaderWrapper(m_vk, device, binaries.get(m_meshShaderName), 0) : vk::ShaderWrapper());
231 	const vk::ShaderWrapper				vs			(m_isMesh ? vk::ShaderWrapper() : vk::ShaderWrapper(m_vk, device, binaries.get(m_vertexShaderName), 0));
232 	const vk::ShaderWrapper				fs			(vk::ShaderWrapper(m_vk, device, binaries.get(m_fragmentShaderName), 0));
233 	std::vector<vk::VkViewport>			viewports	{ { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } };
234 	std::vector<vk::VkRect2D>			scissors	{ { { 0u, 0u }, { 0u, 0u } }};
235 
236 	m_pipeline.setDefaultTopology(m_topology)
237 			  .setDynamicState(static_cast<const vk::VkPipelineDynamicStateCreateInfo*>(&dynamicState));
238 
239 #ifndef CTS_USES_VULKANSC
240 	if (m_isMesh)
241 	{
242 		m_pipeline
243 			  .setupPreRasterizationMeshShaderState(viewports,
244 													scissors,
245 													m_pipelineLayout,
246 													*m_renderPass,
247 													0u,
248 													vk::ShaderWrapper(),
249 													ms,
250 													static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState));
251 	}
252 	else
253 #endif // CTS_USES_VULKANSC
254 	{
255 		m_pipeline
256 			  .setupVertexInputState(&m_vertexInputState)
257 			  .setupPreRasterizationShaderState(viewports,
258 												scissors,
259 												m_pipelineLayout,
260 												*m_renderPass,
261 												0u,
262 												vs,
263 												static_cast<const vk::VkPipelineRasterizationStateCreateInfo*>(&rasterizerState));
264 	}
265 
266 	m_pipeline.setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fs, static_cast<const vk::VkPipelineDepthStencilStateCreateInfo*>(&depthStencilState), &multisampleState)
267 			  .setupFragmentOutputState(*m_renderPass, 0u, static_cast<const vk::VkPipelineColorBlendStateCreateInfo*>(&colorBlendState), &multisampleState)
268 			  .setMonolithicPipelineLayout(m_pipelineLayout)
269 			  .buildPipeline();
270 }
271 
iterate(void)272 tcu::TestStatus DynamicStateBaseClass::iterate (void)
273 {
274 	DE_ASSERT(false);
275 	return tcu::TestStatus::fail("Implement iterate() method!");
276 }
277 
beginRenderPass(void)278 void DynamicStateBaseClass::beginRenderPass (void)
279 {
280 	const vk::VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
281 	beginRenderPassWithClearColor(clearColor);
282 }
283 
beginRenderPassWithClearColor(const vk::VkClearColorValue & clearColor,const bool skipBeginCmdBuffer,const bool previousTransfer)284 void DynamicStateBaseClass::beginRenderPassWithClearColor(const vk::VkClearColorValue& clearColor, const bool skipBeginCmdBuffer, const bool previousTransfer)
285 {
286 	if (!skipBeginCmdBuffer)
287 	{
288 		beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
289 	}
290 
291 	if (previousTransfer)
292 	{
293 		const auto transfer2Transfer = vk::makeMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, (vk::VK_ACCESS_TRANSFER_WRITE_BIT | vk::VK_ACCESS_TRANSFER_READ_BIT));
294 		vk::cmdPipelineMemoryBarrier(m_vk, *m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, &transfer2Transfer);
295 	}
296 	else
297 	{
298 		initialTransitionColor2DImage(m_vk, *m_cmdBuffer, m_colorTargetImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
299 									  vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
300 	}
301 
302 	const ImageSubresourceRange subresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT);
303 	m_vk.cmdClearColorImage(*m_cmdBuffer, m_colorTargetImage->object(),
304 		vk::VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
305 
306 	const vk::VkMemoryBarrier memBarrier =
307 	{
308 		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,
309 		DE_NULL,
310 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,
311 		vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
312 	};
313 
314 	m_vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
315 		vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
316 		0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
317 
318 	m_renderPass.begin(m_vk, *m_cmdBuffer, vk::makeRect2D(0, 0, WIDTH, HEIGHT));
319 }
320 
setDynamicViewportState(const deUint32 width,const deUint32 height)321 void DynamicStateBaseClass::setDynamicViewportState (const deUint32 width, const deUint32 height)
322 {
323 	vk::VkViewport viewport = vk::makeViewport(tcu::UVec2(width, height));
324 	vk::VkRect2D scissor = vk::makeRect2D(tcu::UVec2(width, height));
325 	if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
326 	{
327 #ifndef CTS_USES_VULKANSC
328 		m_vk.cmdSetViewportWithCount(*m_cmdBuffer, 1, &viewport);
329 		m_vk.cmdSetScissorWithCount(*m_cmdBuffer, 1, &scissor);
330 #else
331 		m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, 1, &viewport);
332 		m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, 1, &scissor);
333 #endif
334 	}
335 	else
336 	{
337 		m_vk.cmdSetViewport(*m_cmdBuffer, 0, 1, &viewport);
338 		m_vk.cmdSetScissor(*m_cmdBuffer, 0, 1, &scissor);
339 	}
340 }
341 
setDynamicViewportState(deUint32 viewportCount,const vk::VkViewport * pViewports,const vk::VkRect2D * pScissors)342 void DynamicStateBaseClass::setDynamicViewportState (deUint32 viewportCount, const vk::VkViewport* pViewports, const vk::VkRect2D* pScissors)
343 {
344 	if (vk::isConstructionTypeShaderObject(m_pipelineConstructionType))
345 	{
346 #ifndef CTS_USES_VULKANSC
347 		m_vk.cmdSetViewportWithCount(*m_cmdBuffer, viewportCount, pViewports);
348 		m_vk.cmdSetScissorWithCount(*m_cmdBuffer, viewportCount, pScissors);
349 #else
350 		m_vk.cmdSetViewportWithCountEXT(*m_cmdBuffer, viewportCount, pViewports);
351 		m_vk.cmdSetScissorWithCountEXT(*m_cmdBuffer, viewportCount, pScissors);
352 #endif
353 	}
354 	else
355 	{
356 		m_vk.cmdSetViewport(*m_cmdBuffer, 0, viewportCount, pViewports);
357 		m_vk.cmdSetScissor(*m_cmdBuffer, 0, viewportCount, pScissors);
358 	}
359 }
360 
setDynamicRasterizationState(const float lineWidth,const float depthBiasConstantFactor,const float depthBiasClamp,const float depthBiasSlopeFactor)361 void DynamicStateBaseClass::setDynamicRasterizationState (const float lineWidth,
362 														 const float depthBiasConstantFactor,
363 														 const float depthBiasClamp,
364 														 const float depthBiasSlopeFactor)
365 {
366 	m_vk.cmdSetLineWidth(*m_cmdBuffer, lineWidth);
367 	m_vk.cmdSetDepthBias(*m_cmdBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
368 }
369 
setDynamicBlendState(const float const1,const float const2,const float const3,const float const4)370 void DynamicStateBaseClass::setDynamicBlendState (const float const1, const float const2, const float const3, const float const4)
371 {
372 	float blendConstantsants[4] = { const1, const2, const3, const4 };
373 	m_vk.cmdSetBlendConstants(*m_cmdBuffer, blendConstantsants);
374 }
375 
setDynamicDepthStencilState(const float minDepthBounds,const float maxDepthBounds,const deUint32 stencilFrontCompareMask,const deUint32 stencilFrontWriteMask,const deUint32 stencilFrontReference,const deUint32 stencilBackCompareMask,const deUint32 stencilBackWriteMask,const deUint32 stencilBackReference)376 void DynamicStateBaseClass::setDynamicDepthStencilState (const float	minDepthBounds,
377 														 const float	maxDepthBounds,
378 														 const deUint32 stencilFrontCompareMask,
379 														 const deUint32 stencilFrontWriteMask,
380 														 const deUint32 stencilFrontReference,
381 														 const deUint32 stencilBackCompareMask,
382 														 const deUint32 stencilBackWriteMask,
383 														 const deUint32 stencilBackReference)
384 {
385 	m_vk.cmdSetDepthBounds(*m_cmdBuffer, minDepthBounds, maxDepthBounds);
386 	m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontCompareMask);
387 	m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontWriteMask);
388 	m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_FRONT_BIT, stencilFrontReference);
389 	m_vk.cmdSetStencilCompareMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackCompareMask);
390 	m_vk.cmdSetStencilWriteMask(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackWriteMask);
391 	m_vk.cmdSetStencilReference(*m_cmdBuffer, vk::VK_STENCIL_FACE_BACK_BIT, stencilBackReference);
392 }
393 
394 #ifndef CTS_USES_VULKANSC
pushVertexOffset(const uint32_t vertexOffset,const vk::VkPipelineLayout pipelineLayout,const vk::VkShaderStageFlags stageFlags)395 void DynamicStateBaseClass::pushVertexOffset (const uint32_t				vertexOffset,
396 											  const vk::VkPipelineLayout	pipelineLayout,
397 											  const vk::VkShaderStageFlags	stageFlags)
398 {
399 	m_vk.cmdPushConstants(*m_cmdBuffer, pipelineLayout, stageFlags, 0u, static_cast<uint32_t>(sizeof(uint32_t)), &vertexOffset);
400 }
401 #endif // CTS_USES_VULKANSC
402 
403 } // DynamicState
404 } // vkt
405