• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2021 Valve 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 mixing it with compute and transfer.
23  *//*--------------------------------------------------------------------*/
24 #include "vktDynamicStateComputeTests.hpp"
25 #include "vktCustomInstancesDevices.hpp"
26 
27 #include "vkBufferWithMemory.hpp"
28 #include "vkObjUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkBarrierUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 
34 #include "tcuCommandLine.hpp"
35 #include "tcuVector.hpp"
36 
37 #include <vector>
38 #include <string>
39 #include <functional>
40 #include <map>
41 #include <sstream>
42 #include <cstring>
43 #include <iterator>
44 #include <numeric>
45 #include <memory>
46 
47 namespace vkt
48 {
49 namespace DynamicState
50 {
51 
52 namespace
53 {
54 
55 using namespace vk;
56 
57 // Additional objects needed to set a given dynamic state that need to exist beyond the state-setting call. Empty by default.
58 struct DynamicStateData
59 {
~DynamicStateDatavkt::DynamicState::__anond426403c0111::DynamicStateData60 	virtual ~DynamicStateData() {}
61 };
62 
63 // A vertex buffer and graphics pipeline are needed for vkCmdBindVertexBuffers2EXT().
64 struct BindVertexBuffersData : public DynamicStateData
65 {
66 private:
67 	using BufferPtr			= de::MovePtr<BufferWithMemory>;
68 	using RenderPassPtr		= Move<VkRenderPass>;
69 	using LayoutPtr			= Move<VkPipelineLayout>;
70 	using ModulePtr			= Move<VkShaderModule>;
71 	using PipelinePtr		= Move<VkPipeline>;
72 
73 	static constexpr deUint32 kWidth	= 16u;
74 	static constexpr deUint32 kHeight	= 16u;
75 
getExtentvkt::DynamicState::__anond426403c0111::BindVertexBuffersData76 	VkExtent3D getExtent (void)
77 	{
78 		return makeExtent3D(kWidth, kHeight, 1u);
79 	}
80 
81 public:
BindVertexBuffersDatavkt::DynamicState::__anond426403c0111::BindVertexBuffersData82 	BindVertexBuffersData(Context& ctx, VkDevice device)
83 		: m_vertexBuffer		()
84 		, m_dataSize			(0u)
85 		, m_vertexBufferSize	(0ull)
86 		, m_renderPass			()
87 		, m_pipelineLayout		()
88 		, m_vertexShader		()
89 		, m_graphicsPipeline	()
90 	{
91 		const auto&	vki			= ctx.getInstanceInterface();
92 		const auto	phyDev		= ctx.getPhysicalDevice();
93 		const auto&	vkd			= ctx.getDeviceInterface();
94 		auto&		alloc		= ctx.getDefaultAllocator();
95 
96 		// Vertex buffer.
97 		tcu::Vec4	vertex		(0.f, 0.f, 0.f, 1.f);
98 		m_dataSize				= sizeof(vertex);
99 		m_vertexBufferSize		= de::roundUp(static_cast<VkDeviceSize>(m_dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
100 		const auto	bufferInfo	= makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
101 
102 		m_vertexBuffer			= BufferPtr(new BufferWithMemory(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible));
103 		auto&	bufferAlloc		= m_vertexBuffer->getAllocation();
104 
105 		deMemcpy(bufferAlloc.getHostPtr(), &vertex, m_dataSize);
106 		flushAlloc(vkd, device, bufferAlloc);
107 
108 		// Empty render pass.
109 		m_renderPass = makeRenderPass(vkd, device);
110 
111 		// Empty pipeline layout.
112 		m_pipelineLayout = makePipelineLayout(vkd, device);
113 
114 		// Passthrough vertex shader.
115 		m_vertexShader = createShaderModule(vkd, device, ctx.getBinaryCollection().get("vert"), 0u);
116 
117 		const auto						extent		= getExtent();
118 		const std::vector<VkViewport>	viewports	(1, makeViewport(extent));
119 		const std::vector<VkRect2D>		scissors	(1, makeRect2D(extent));
120 		const VkDynamicState			state		= VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
121 
122 		const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
123 		{
124 			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
125 			nullptr,												//	const void*							pNext;
126 			0u,														//	VkPipelineDynamicStateCreateFlags	flags;
127 			1u,														//	deUint32							dynamicStateCount;
128 			&state,													//	const VkDynamicState*				pDynamicStates;
129 		};
130 
131 		// Graphics pipeline.
132 		m_graphicsPipeline = makeGraphicsPipeline(vkd, device, m_pipelineLayout.get(),
133 			m_vertexShader.get(), DE_NULL, DE_NULL, DE_NULL, DE_NULL,
134 			m_renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
135 			nullptr, nullptr, nullptr, nullptr, nullptr, &dynamicStateInfo);
136 	}
137 
getVertexBuffervkt::DynamicState::__anond426403c0111::BindVertexBuffersData138 	const BufferWithMemory*	getVertexBuffer () const
139 	{
140 		return m_vertexBuffer.get();
141 	}
142 
getDataSizevkt::DynamicState::__anond426403c0111::BindVertexBuffersData143 	size_t getDataSize () const
144 	{
145 		return m_dataSize;
146 	}
147 
getPipelinevkt::DynamicState::__anond426403c0111::BindVertexBuffersData148 	VkPipeline getPipeline () const
149 	{
150 		return m_graphicsPipeline.get();
151 	}
152 
~BindVertexBuffersDatavkt::DynamicState::__anond426403c0111::BindVertexBuffersData153 	virtual ~BindVertexBuffersData() {}
154 
155 private:
156 	BufferPtr		m_vertexBuffer;
157 	size_t			m_dataSize;
158 	VkDeviceSize	m_vertexBufferSize;
159 	RenderPassPtr	m_renderPass;
160 	LayoutPtr		m_pipelineLayout;
161 	ModulePtr		m_vertexShader;
162 	PipelinePtr		m_graphicsPipeline;
163 };
164 
165 // Function that records a state-setting command in the given command buffer.
166 using RecordStateFunction = std::function<void(const DeviceInterface*, VkCommandBuffer, const DynamicStateData*)>;
167 
168 // State-setting functions
setViewport(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)169 void setViewport (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
170 {
171 	const VkViewport viewport =
172 	{
173 		0.0f,	//	float	x;
174 		0.0f,	//	float	y;
175 		1.0f,	//	float	width;
176 		1.0f,	//	float	height;
177 		0.0f,	//	float	minDepth;
178 		1.0f,	//	float	maxDepth;
179 	};
180 	vkd->cmdSetViewport(cmdBuffer, 0u, 1u, &viewport);
181 }
182 
setScissor(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)183 void setScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
184 {
185 	const VkRect2D scissor =
186 	{
187 		{ 0, 0 },	//	VkOffset2D	offset;
188 		{ 1u, 1u },	//	VkExtent2D	extent;
189 	};
190 	vkd->cmdSetScissor(cmdBuffer, 0u, 1u, &scissor);
191 }
192 
setLineWidth(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)193 void setLineWidth (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
194 {
195 	vkd->cmdSetLineWidth(cmdBuffer, 1.0f);
196 }
197 
setDepthBias(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)198 void setDepthBias (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
199 {
200 	vkd->cmdSetDepthBias(cmdBuffer, 0.0f, 0.0f, 0.0f);
201 }
202 
setBlendConstants(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)203 void setBlendConstants (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
204 {
205 	const float blendConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
206 	vkd->cmdSetBlendConstants(cmdBuffer, blendConstants);
207 }
208 
setDepthBounds(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)209 void setDepthBounds (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
210 {
211 	vkd->cmdSetDepthBounds(cmdBuffer, 0.0f, 1.0f);
212 }
213 
setStencilCompareMask(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)214 void setStencilCompareMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
215 {
216 	vkd->cmdSetStencilCompareMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
217 }
218 
setStencilWriteMask(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)219 void setStencilWriteMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
220 {
221 	vkd->cmdSetStencilWriteMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
222 }
223 
setStencilReference(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)224 void setStencilReference (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
225 {
226 	vkd->cmdSetStencilReference(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
227 }
228 
setDiscardRectangle(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)229 void setDiscardRectangle (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
230 {
231 	const VkRect2D rectangle =
232 	{
233 		{ 0, 0 },	//	VkOffset2D	offset;
234 		{ 1u, 1u },	//	VkExtent2D	extent;
235 	};
236 	vkd->cmdSetDiscardRectangleEXT(cmdBuffer, 0u, 1u, &rectangle);
237 }
238 
setSampleLocations(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)239 void setSampleLocations (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
240 {
241 	const VkSampleLocationEXT locations[] =
242 	{
243 		{ 0.5f, 0.5f },
244 		{ 0.5f, 1.5f },
245 		{ 1.5f, 0.5f },
246 		{ 1.5f, 1.5f },
247 	};
248 	const VkSampleLocationsInfoEXT info =
249 	{
250 		VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,	//	VkStructureType				sType;
251 		nullptr,										//	const void*					pNext;
252 		VK_SAMPLE_COUNT_4_BIT,							//	VkSampleCountFlagBits		sampleLocationsPerPixel;
253 		{ 1u, 1u },										//	VkExtent2D					sampleLocationGridSize;
254 		4u,												//	deUint32					sampleLocationsCount;
255 		locations,										//	const VkSampleLocationEXT*	pSampleLocations;
256 	};
257 	vkd->cmdSetSampleLocationsEXT(cmdBuffer, &info);
258 }
259 
260 #ifndef CTS_USES_VULKANSC
setRTPipelineStatckSize(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)261 void setRTPipelineStatckSize (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
262 {
263 	vkd->cmdSetRayTracingPipelineStackSizeKHR(cmdBuffer, 4096u);
264 }
265 #endif // CTS_USES_VULKANSC
266 
setFragmentShadingRage(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)267 void setFragmentShadingRage (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
268 {
269 	const VkExtent2D							fragmentSize	= { 1u, 1u };
270 	const VkFragmentShadingRateCombinerOpKHR	combinerOps[2]	=
271 	{
272 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
273 		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
274 	};
275 	vkd->cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, combinerOps);
276 }
277 
setLineStipple(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)278 void setLineStipple (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
279 {
280 	vkd->cmdSetLineStippleEXT(cmdBuffer, 1u, 1u);
281 }
282 
setCullMode(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)283 void setCullMode (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
284 {
285 #ifndef CTS_USES_VULKANSC
286 	vkd->cmdSetCullMode(cmdBuffer, VK_CULL_MODE_FRONT_AND_BACK);
287 #else
288 	vkd->cmdSetCullModeEXT(cmdBuffer, VK_CULL_MODE_FRONT_AND_BACK);
289 #endif // CTS_USES_VULKANSC
290 }
291 
setFrontFace(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)292 void setFrontFace (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
293 {
294 #ifndef CTS_USES_VULKANSC
295 	vkd->cmdSetFrontFace(cmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
296 #else
297 	vkd->cmdSetFrontFaceEXT(cmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
298 #endif // CTS_USES_VULKANSC
299 }
300 
setPrimitiveTopology(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)301 void setPrimitiveTopology (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
302 {
303 #ifndef CTS_USES_VULKANSC
304 	vkd->cmdSetPrimitiveTopology(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
305 #else
306 	vkd->cmdSetPrimitiveTopologyEXT(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
307 #endif // CTS_USES_VULKANSC
308 }
309 
setViewportWithCount(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)310 void setViewportWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
311 {
312 	const VkViewport viewport =
313 	{
314 		0.0f,	//	float	x;
315 		0.0f,	//	float	y;
316 		1.0f,	//	float	width;
317 		1.0f,	//	float	height;
318 		0.0f,	//	float	minDepth;
319 		1.0f,	//	float	maxDepth;
320 	};
321 #ifndef CTS_USES_VULKANSC
322 	vkd->cmdSetViewportWithCount(cmdBuffer, 1u, &viewport);
323 #else
324 	vkd->cmdSetViewportWithCountEXT(cmdBuffer, 1u, &viewport);
325 #endif // CTS_USES_VULKANSC
326 }
327 
setScissorWithCount(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)328 void setScissorWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
329 {
330 	const VkRect2D scissor =
331 	{
332 		{ 0, 0 },	//	VkOffset2D	offset;
333 		{ 1u, 1u },	//	VkExtent2D	extent;
334 	};
335 #ifndef CTS_USES_VULKANSC
336 	vkd->cmdSetScissorWithCount(cmdBuffer, 1u, &scissor);
337 #else
338 	vkd->cmdSetScissorWithCountEXT(cmdBuffer, 1u, &scissor);
339 #endif // CTS_USES_VULKANSC
340 }
341 
bindVertexBuffers(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData * data)342 void bindVertexBuffers (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData* data)
343 {
344 	const auto bindData			= dynamic_cast<const BindVertexBuffersData*>(data);
345 	DE_ASSERT(bindData != nullptr);
346 	const auto vertexBuffer		= bindData->getVertexBuffer();
347 	const auto dataSize			= static_cast<VkDeviceSize>(bindData->getDataSize());
348 	const auto bufferOffset		= vertexBuffer->getAllocation().getOffset();
349 	const auto stride			= static_cast<VkDeviceSize>(0);
350 	const auto pipeline			= bindData->getPipeline();
351 
352 	vkd->cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
353 #ifndef CTS_USES_VULKANSC
354 	vkd->cmdBindVertexBuffers2(cmdBuffer, 0u, 1u, &vertexBuffer->get(), &bufferOffset, &dataSize, &stride);
355 #else
356 	vkd->cmdBindVertexBuffers2EXT(cmdBuffer, 0u, 1u, &vertexBuffer->get(), &bufferOffset, &dataSize, &stride);
357 #endif // CTS_USES_VULKANSC
358 }
359 
setDepthTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)360 void setDepthTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
361 {
362 #ifndef CTS_USES_VULKANSC
363 	vkd->cmdSetDepthTestEnable(cmdBuffer, VK_TRUE);
364 #else
365 	vkd->cmdSetDepthTestEnableEXT(cmdBuffer, VK_TRUE);
366 #endif // CTS_USES_VULKANSC
367 }
368 
setDepthWriteEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)369 void setDepthWriteEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
370 {
371 #ifndef CTS_USES_VULKANSC
372 	vkd->cmdSetDepthWriteEnable(cmdBuffer, VK_TRUE);
373 #else
374 	vkd->cmdSetDepthWriteEnableEXT(cmdBuffer, VK_TRUE);
375 #endif // CTS_USES_VULKANSC
376 }
377 
setDepthCompareOp(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)378 void setDepthCompareOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
379 {
380 #ifndef CTS_USES_VULKANSC
381 	vkd->cmdSetDepthCompareOp(cmdBuffer, VK_COMPARE_OP_LESS);
382 #else
383 	vkd->cmdSetDepthCompareOpEXT(cmdBuffer, VK_COMPARE_OP_LESS);
384 #endif // CTS_USES_VULKANSC
385 }
386 
setDepthBoundsTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)387 void setDepthBoundsTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
388 {
389 #ifndef CTS_USES_VULKANSC
390 	vkd->cmdSetDepthBoundsTestEnable(cmdBuffer, VK_TRUE);
391 #else
392 	vkd->cmdSetDepthBoundsTestEnableEXT(cmdBuffer, VK_TRUE);
393 #endif // CTS_USES_VULKANSC
394 }
395 
setStencilTestEnable(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)396 void setStencilTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
397 {
398 #ifndef CTS_USES_VULKANSC
399 	vkd->cmdSetStencilTestEnable(cmdBuffer, VK_TRUE);
400 #else
401 	vkd->cmdSetStencilTestEnableEXT(cmdBuffer, VK_TRUE);
402 #endif // CTS_USES_VULKANSC
403 }
404 
setStencilOp(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)405 void setStencilOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
406 {
407 #ifndef CTS_USES_VULKANSC
408 	vkd->cmdSetStencilOp(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
409 #else
410 	vkd->cmdSetStencilOpEXT(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
411 #endif // CTS_USES_VULKANSC
412 }
413 
414 #ifndef CTS_USES_VULKANSC
415 
setViewportWScaling(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)416 void setViewportWScaling (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
417 {
418 	const VkViewportWScalingNV viewport =
419 	{
420 		1.0f,	//	float	xcoeff;
421 		1.0f,	//	float	ycoeff;
422 	};
423 	vkd->cmdSetViewportWScalingNV(cmdBuffer, 0u, 1u, &viewport);
424 }
425 
setViewportShadingRatePalette(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)426 void setViewportShadingRatePalette (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
427 {
428 	const VkShadingRatePaletteEntryNV	entry	= VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
429 	const VkShadingRatePaletteNV		palette	=
430 	{
431 		1u,		//	deUint32							shadingRatePaletteEntryCount;
432 		&entry,	//	const VkShadingRatePaletteEntryNV*	pShadingRatePaletteEntries;
433 	};
434 	vkd->cmdSetViewportShadingRatePaletteNV(cmdBuffer, 0u, 1u, &palette);
435 }
436 
setCoarseSamplingOrder(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)437 void setCoarseSamplingOrder (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
438 {
439 	const VkCoarseSampleLocationNV locations[2] =
440 	{
441 		{
442 			0u,	//	deUint32	pixelX;
443 			0u,	//	deUint32	pixelY;
444 			0u,	//	deUint32	sample;
445 		},
446 		{
447 			0u,	//	deUint32	pixelX;
448 			1u,	//	deUint32	pixelY;
449 			0u,	//	deUint32	sample;
450 		},
451 	};
452 	const VkCoarseSampleOrderCustomNV order =
453 	{
454 		VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV,	//	VkShadingRatePaletteEntryNV		shadingRate;
455 		1u,																//	deUint32						sampleCount;
456 		2u,																//	deUint32						sampleLocationCount;
457 		locations														//	const VkCoarseSampleLocationNV*	pSampleLocations;
458 	};
459 	vkd->cmdSetCoarseSampleOrderNV(cmdBuffer, VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV, 1u, &order);
460 }
461 
setExclusiveScissor(const DeviceInterface * vkd,VkCommandBuffer cmdBuffer,const DynamicStateData *)462 void setExclusiveScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
463 {
464 	const VkRect2D scissor =
465 	{
466 		{ 0, 0 },	//	VkOffset2D	offset;
467 		{ 1u, 1u },	//	VkExtent2D	extent;
468 	};
469 	vkd->cmdSetExclusiveScissorNV(cmdBuffer, 0u, 1u, &scissor);
470 }
471 
472 #endif // CTS_USES_VULKANSC
473 
474 const VkDynamicState dynamicStateList[] =
475 {
476 	VK_DYNAMIC_STATE_VIEWPORT,
477 	VK_DYNAMIC_STATE_SCISSOR,
478 	VK_DYNAMIC_STATE_LINE_WIDTH,
479 	VK_DYNAMIC_STATE_DEPTH_BIAS,
480 	VK_DYNAMIC_STATE_BLEND_CONSTANTS,
481 	VK_DYNAMIC_STATE_DEPTH_BOUNDS,
482 	VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
483 	VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
484 	VK_DYNAMIC_STATE_STENCIL_REFERENCE,
485 	VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
486 	VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
487 #ifndef CTS_USES_VULKANSC
488 	VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR,
489 #endif // CTS_USES_VULKANSC
490 	VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
491 	VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
492 	VK_DYNAMIC_STATE_CULL_MODE_EXT,
493 	VK_DYNAMIC_STATE_FRONT_FACE_EXT,
494 	VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
495 	VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
496 	VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
497 	VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
498 	VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
499 	VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
500 	VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
501 	VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
502 	VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
503 	VK_DYNAMIC_STATE_STENCIL_OP_EXT,
504 #ifndef CTS_USES_VULKANSC
505 	VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
506 	VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
507 	VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
508 	VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
509 #endif // CTS_USES_VULKANSC
510 };
511 
512 // Information about a dynamic state.
513 struct StateInfo
514 {
515 	std::vector<std::string>	requirements;	// List of required functionalities.
516 	RecordStateFunction			recorder;		// Function that records the state to the command buffer being used.
517 };
518 
519 // Returns the state info for a given dynamic state.
getDynamicStateInfo(VkDynamicState state)520 const StateInfo& getDynamicStateInfo (VkDynamicState state)
521 {
522 	// Maps a given state to its state info structure.
523 	using StateInfoMap = std::map<VkDynamicState, StateInfo>;
524 
525 	static const StateInfoMap result =
526 	{
527 		{	VK_DYNAMIC_STATE_VIEWPORT,								{	{},										setViewport						}	},
528 		{	VK_DYNAMIC_STATE_SCISSOR,								{	{},										setScissor						}	},
529 		{	VK_DYNAMIC_STATE_LINE_WIDTH,							{	{},										setLineWidth					}	},
530 		{	VK_DYNAMIC_STATE_DEPTH_BIAS,							{	{},										setDepthBias					}	},
531 		{	VK_DYNAMIC_STATE_BLEND_CONSTANTS,						{	{},										setBlendConstants				}	},
532 		{	VK_DYNAMIC_STATE_DEPTH_BOUNDS,							{	{},										setDepthBounds					}	},
533 		{	VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,					{	{},										setStencilCompareMask			}	},
534 		{	VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,					{	{},										setStencilWriteMask				}	},
535 		{	VK_DYNAMIC_STATE_STENCIL_REFERENCE,						{	{},										setStencilReference				}	},
536 		{	VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,					{	{ "VK_EXT_discard_rectangles" },		setDiscardRectangle				}	},
537 		{	VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,					{	{ "VK_EXT_sample_locations" },			setSampleLocations				}	},
538 #ifndef CTS_USES_VULKANSC
539 		{	VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR,	{	{ "VK_KHR_ray_tracing_pipeline" },		setRTPipelineStatckSize			}	},
540 #endif // CTS_USES_VULKANSC
541 		{	VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,				{	{ "VK_KHR_fragment_shading_rate" },		setFragmentShadingRage			}	},
542 		{	VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,						{	{ "VK_EXT_line_rasterization" },		setLineStipple					}	},
543 		{	VK_DYNAMIC_STATE_CULL_MODE_EXT,							{	{ "VK_EXT_extended_dynamic_state" },	setCullMode						}	},
544 		{	VK_DYNAMIC_STATE_FRONT_FACE_EXT,						{	{ "VK_EXT_extended_dynamic_state" },	setFrontFace					}	},
545 		{	VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setPrimitiveTopology			}	},
546 		{	VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setViewportWithCount			}	},
547 		{	VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setScissorWithCount				}	},
548 		{	VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,		{	{ "VK_EXT_extended_dynamic_state" },	bindVertexBuffers				}	},
549 		{	VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,					{	{ "VK_EXT_extended_dynamic_state" },	setDepthTestEnable				}	},
550 		{	VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setDepthWriteEnable				}	},
551 		{	VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,					{	{ "VK_EXT_extended_dynamic_state" },	setDepthCompareOp				}	},
552 		{	VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,			{	{ "VK_EXT_extended_dynamic_state" },	setDepthBoundsTestEnable		}	},
553 		{	VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setStencilTestEnable			}	},
554 		{	VK_DYNAMIC_STATE_STENCIL_OP_EXT,						{	{ "VK_EXT_extended_dynamic_state" },	setStencilOp					}	},
555 #ifndef CTS_USES_VULKANSC
556 		{	VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,					{	{ "VK_NV_clip_space_w_scaling" },		setViewportWScaling				}	},
557 		{	VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,		{	{ "VK_NV_shading_rate_image"},			setViewportShadingRatePalette	}	},
558 		{	VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,		{	{ "VK_NV_shading_rate_image"},			setCoarseSamplingOrder			}	},
559 		{	VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,					{	{ "VK_NV_scissor_exclusive"},			setExclusiveScissor				}	},
560 #endif // CTS_USES_VULKANSC
561 	};
562 
563 	const auto itr = result.find(state);
564 	DE_ASSERT(itr != result.end());
565 
566 	return itr->second;
567 }
568 
569 // Device helper: this is needed in some tests when we create custom devices.
570 class DeviceHelper
571 {
572 public:
~DeviceHelper()573 	virtual ~DeviceHelper () {}
574 	virtual const DeviceInterface&	getDeviceInterface	(void) const = 0;
575 	virtual VkDevice				getDevice			(void) const = 0;
576 	virtual uint32_t				getQueueFamilyIndex	(void) const = 0;
577 	virtual VkQueue					getQueue			(void) const = 0;
578 	virtual Allocator&				getAllocator		(void) const = 0;
579 };
580 
581 // This one just reuses the default device from the context.
582 class ContextDeviceHelper : public DeviceHelper
583 {
584 public:
ContextDeviceHelper(Context & context)585 	ContextDeviceHelper (Context& context)
586 		: m_deviceInterface		(context.getDeviceInterface())
587 		, m_device				(context.getDevice())
588 		, m_queueFamilyIndex	(context.getUniversalQueueFamilyIndex())
589 		, m_queue				(context.getUniversalQueue())
590 		, m_allocator			(context.getDefaultAllocator())
591 		{}
592 
~ContextDeviceHelper()593 	virtual ~ContextDeviceHelper () {}
594 
getDeviceInterface(void) const595 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return m_deviceInterface;		}
getDevice(void) const596 	VkDevice				getDevice			(void) const override	{ return m_device;				}
getQueueFamilyIndex(void) const597 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const598 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const599 	Allocator&				getAllocator		(void) const override	{ return m_allocator;			}
600 
601 protected:
602 	const DeviceInterface&	m_deviceInterface;
603 	const VkDevice			m_device;
604 	const uint32_t			m_queueFamilyIndex;
605 	const VkQueue			m_queue;
606 	Allocator&				m_allocator;
607 };
608 
609 // This one creates a new device with VK_NV_shading_rate_image.
610 class ShadingRateImageDeviceHelper : public DeviceHelper
611 {
612 public:
ShadingRateImageDeviceHelper(Context & context)613 	ShadingRateImageDeviceHelper (Context& context)
614 	{
615 		const auto&	vkp				= context.getPlatformInterface();
616 		const auto&	vki				= context.getInstanceInterface();
617 		const auto	instance		= context.getInstance();
618 		const auto	physicalDevice	= context.getPhysicalDevice();
619 		const auto	queuePriority	= 1.0f;
620 
621 		// Queue index first.
622 		m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
623 
624 		// Create a universal queue that supports graphics and compute.
625 		const VkDeviceQueueCreateInfo queueParams =
626 		{
627 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType				sType;
628 			DE_NULL,									// const void*					pNext;
629 			0u,											// VkDeviceQueueCreateFlags		flags;
630 			m_queueFamilyIndex,							// deUint32						queueFamilyIndex;
631 			1u,											// deUint32						queueCount;
632 			&queuePriority								// const float*					pQueuePriorities;
633 		};
634 
635 		const char* extensions[] =
636 		{
637 			"VK_NV_shading_rate_image",
638 		};
639 
640 #ifndef CTS_USES_VULKANSC
641 		VkPhysicalDeviceShadingRateImageFeaturesNV	shadingRateImageFeatures	= initVulkanStructure();
642 		VkPhysicalDeviceFeatures2					features2					= initVulkanStructure(&shadingRateImageFeatures);
643 
644 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
645 #endif // CTS_USES_VULKANSC
646 
647 		const VkDeviceCreateInfo deviceCreateInfo =
648 		{
649 			VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,					//sType;
650 #ifndef CTS_USES_VULKANSC
651 			&features2,												//pNext;
652 #else
653 			DE_NULL,
654 #endif // CTS_USES_VULKANSC
655 			0u,														//flags
656 			1u,														//queueRecordCount;
657 			&queueParams,											//pRequestedQueues;
658 			0u,														//layerCount;
659 			nullptr,												//ppEnabledLayerNames;
660 			static_cast<uint32_t>(de::arrayLength(extensions)),		// deUint32							enabledExtensionCount;
661 			extensions,												// const char* const*				ppEnabledExtensionNames;
662 			nullptr,												//pEnabledFeatures;
663 		};
664 
665 		m_device	= createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
666 		m_vkd		.reset(new DeviceDriver(vkp, instance, m_device.get()));
667 		m_queue		= getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
668 		m_allocator	.reset(new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
669 	}
670 
~ShadingRateImageDeviceHelper()671 	virtual ~ShadingRateImageDeviceHelper () {}
672 
getDeviceInterface(void) const673 	const DeviceInterface&	getDeviceInterface	(void) const override	{ return *m_vkd;				}
getDevice(void) const674 	VkDevice				getDevice			(void) const override	{ return m_device.get();		}
getQueueFamilyIndex(void) const675 	uint32_t				getQueueFamilyIndex	(void) const override	{ return m_queueFamilyIndex;	}
getQueue(void) const676 	VkQueue					getQueue			(void) const override	{ return m_queue;				}
getAllocator(void) const677 	Allocator&				getAllocator		(void) const override	{ return *m_allocator;			}
678 
679 protected:
680 	Move<VkDevice>						m_device;
681 	std::unique_ptr<DeviceDriver>		m_vkd;
682 	deUint32							m_queueFamilyIndex;
683 	VkQueue								m_queue;
684 	std::unique_ptr<SimpleAllocator>	m_allocator;
685 };
686 
687 std::unique_ptr<DeviceHelper> g_shadingRateDeviceHelper;
688 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
689 
getDeviceHelper(Context & context,VkDynamicState dynamicState)690 DeviceHelper& getDeviceHelper(Context& context, VkDynamicState dynamicState)
691 {
692 	const auto& stateInfo = getDynamicStateInfo(dynamicState);
693 
694 	if (de::contains(stateInfo.requirements.begin(), stateInfo.requirements.end(), "VK_NV_shading_rate_image"))
695 	{
696 		if (!g_shadingRateDeviceHelper)
697 			g_shadingRateDeviceHelper.reset(new ShadingRateImageDeviceHelper(context));
698 		return *g_shadingRateDeviceHelper;
699 	}
700 
701 	if (!g_contextDeviceHelper)
702 		g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
703 	return *g_contextDeviceHelper;
704 }
705 
706 // Returns the set of auxiliary data needed to set a given state.
getDynamicStateData(Context & ctx,VkDevice device,VkDynamicState state)707 de::MovePtr<DynamicStateData> getDynamicStateData (Context& ctx, VkDevice device, VkDynamicState state)
708 {
709 	// Create vertex buffer for VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT.
710 	if (state == VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT)
711 		return de::MovePtr<DynamicStateData>(new BindVertexBuffersData(ctx, device));
712 
713 	// null pointer normally.
714 	return de::MovePtr<DynamicStateData>();
715 }
716 
717 enum class OperType		{ COMPUTE = 0,	TRANSFER	};
718 enum class WhenToSet	{ BEFORE = 0,	AFTER		};
719 
720 // Set dynamic state before or after attempting to run a compute or transfer operation.
721 struct TestParams
722 {
723 	OperType					operationType;
724 	WhenToSet					whenToSet;
725 	std::vector<VkDynamicState>	states;
726 };
727 
728 class DynamicStateComputeCase : public vkt::TestCase
729 {
730 public:
731 
732 							DynamicStateComputeCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
~DynamicStateComputeCase(void)733 	virtual					~DynamicStateComputeCase	(void) {}
734 
735 	virtual void			checkSupport				(Context& context) const;
736 	virtual void			initPrograms				(vk::SourceCollections& programCollection) const;
737 	virtual TestInstance*	createInstance				(Context& context) const;
738 
739 protected:
740 	TestParams				m_params;
741 };
742 
743 class DynamicStateComputeInstance : public vkt::TestInstance
744 {
745 public:
746 								DynamicStateComputeInstance		(Context& context, const TestParams& params);
~DynamicStateComputeInstance(void)747 	virtual						~DynamicStateComputeInstance	(void) {}
748 
749 	virtual tcu::TestStatus		iterate							(void);
750 
751 protected:
752 	tcu::TestStatus				iterateTransfer					(void);
753 	tcu::TestStatus				iterateCompute					(void);
754 
755 	TestParams					m_params;
756 };
757 
DynamicStateComputeCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const TestParams & params)758 DynamicStateComputeCase::DynamicStateComputeCase(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
759 	: vkt::TestCase	(testCtx, name, description)
760 	, m_params		(params)
761 {}
762 
DynamicStateComputeInstance(Context & context,const TestParams & params)763 DynamicStateComputeInstance::DynamicStateComputeInstance (Context& context, const TestParams& params)
764 	: vkt::TestInstance (context)
765 	, m_params			(params)
766 {}
767 
checkSupport(Context & context) const768 void DynamicStateComputeCase::checkSupport (Context& context) const
769 {
770 	// Check required functionalities.
771 	for (const auto& state : m_params.states)
772 	{
773 		const auto stateInfo = getDynamicStateInfo(state);
774 		for (const auto& functionality : stateInfo.requirements)
775 			context.requireDeviceFunctionality(functionality);
776 	}
777 }
778 
initPrograms(vk::SourceCollections & programCollection) const779 void DynamicStateComputeCase::initPrograms (vk::SourceCollections& programCollection) const
780 {
781 	if (m_params.operationType == OperType::COMPUTE)
782 	{
783 		std::ostringstream comp;
784 		comp
785 			<< "#version 450\n"
786 			<< "\n"
787 			<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
788 			<< "\n"
789 			<< "layout (push_constant, std430) uniform PushConstants {\n"
790 			<< "	uint valueIndex;\n"
791 			<< "} pc;\n"
792 			<< "\n"
793 			<< "layout (set=0, binding=0, std430) buffer OutputBlock {\n"
794 			<< "	uint value[];\n"
795 			<< "} ob;\n"
796 			<< "\n"
797 			<< "void main ()\n"
798 			<< "{\n"
799 			<< "	ob.value[pc.valueIndex] = 1u;\n"
800 			<< "}\n"
801 			;
802 
803 		programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
804 	}
805 
806 	if (de::contains(begin(m_params.states), end(m_params.states), VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT))
807 	{
808 		// Passthrough vertex shader for stand-in graphics pipeline.
809 		std::ostringstream vert;
810 		vert
811 			<< "#version 450\n"
812 			<< "layout (location=0) in vec4 inVertex;\n"
813 			<< "void main() {\n"
814 			<< "    gl_Position = inVertex;\n"
815 			<< "}\n"
816 			;
817 
818 		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
819 	}
820 }
821 
createInstance(Context & context) const822 vkt::TestInstance* DynamicStateComputeCase::createInstance (Context& context) const
823 {
824 	return new DynamicStateComputeInstance(context, m_params);
825 }
826 
iterate(void)827 tcu::TestStatus DynamicStateComputeInstance::iterate (void)
828 {
829 	if (m_params.operationType == OperType::COMPUTE)
830 		return iterateCompute();
831 	else
832 		return iterateTransfer();
833 }
834 
fillBuffer(const DeviceInterface & vkd,VkDevice device,BufferWithMemory & buffer,const std::vector<deUint32> & values)835 void fillBuffer(const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, const std::vector<deUint32> &values)
836 {
837 	auto& alloc = buffer.getAllocation();
838 
839 	deMemcpy(alloc.getHostPtr(), values.data(), de::dataSize(values));
840 	flushAlloc(vkd, device, alloc);
841 }
842 
iterateTransfer(void)843 tcu::TestStatus DynamicStateComputeInstance::iterateTransfer (void)
844 {
845 	const auto&	vki			= m_context.getInstanceInterface();
846 	const auto	phyDev		= m_context.getPhysicalDevice();
847 	auto&		devHelper	= getDeviceHelper(m_context, m_params.states.at(0));
848 	const auto&	vkd			= devHelper.getDeviceInterface();
849 	const auto	device		= devHelper.getDevice();
850 	const auto	qIndex		= devHelper.getQueueFamilyIndex();
851 	const auto	queue		= devHelper.getQueue();
852 	auto&		alloc		= devHelper.getAllocator();
853 
854 	const auto	cmdPool			= makeCommandPool(vkd, device, qIndex);
855 	const auto	cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
856 	const auto	cmdBuffer		= cmdBufferPtr.get();
857 
858 	// Prepare two host-visible buffers for a transfer operation, with one element per dynamic state.
859 	const deUint32		seqStart	= 1611747605u;
860 
861 	DE_ASSERT(!m_params.states.empty());
862 	std::vector<deUint32>		srcValues(m_params.states.size());
863 	const decltype(srcValues)	dstValues(srcValues.size(), 0u);
864 	std::iota(begin(srcValues), end(srcValues), seqStart);
865 
866 	const auto			elemSize	= static_cast<VkDeviceSize>(sizeof(decltype(srcValues)::value_type));
867 	const auto			dataSize	= static_cast<VkDeviceSize>(de::dataSize(srcValues));
868 	const auto			bufferSize	= de::roundUp(dataSize, getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
869 	const auto			srcInfo		= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
870 	const auto			dstInfo		= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
871 	BufferWithMemory	srcBuffer	(vkd, device, alloc, srcInfo, MemoryRequirement::HostVisible);
872 	BufferWithMemory	dstBuffer	(vkd, device, alloc, dstInfo, MemoryRequirement::HostVisible);
873 
874 	// Fill source and destination buffer.
875 	fillBuffer(vkd, device, srcBuffer, srcValues);
876 	fillBuffer(vkd, device, dstBuffer, dstValues);
877 
878 	beginCommandBuffer(vkd, cmdBuffer);
879 
880 	// We need to preserve dynamic state data until the command buffer has run.
881 	std::vector<de::MovePtr<DynamicStateData>> statesData;
882 
883 	for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
884 	{
885 		// Get extra data needed for using the dynamic state.
886 		const auto	offset		= elemSize * stateIdx;
887 		const auto&	state		= m_params.states[stateIdx];
888 		const auto	stateInfo	= getDynamicStateInfo(state);
889 		statesData.push_back(getDynamicStateData(m_context, device, state));
890 
891 		// Record command if before.
892 		if (m_params.whenToSet == WhenToSet::BEFORE)
893 			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
894 
895 		// Transfer op (copy one buffer element per dynamic state).
896 		const VkBufferCopy region = { offset, offset, elemSize };
897 		vkd.cmdCopyBuffer(cmdBuffer, srcBuffer.get(), dstBuffer.get(), 1u, &region);
898 
899 		// Record command if after.
900 		if (m_params.whenToSet == WhenToSet::AFTER)
901 			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
902 	}
903 
904 	const auto barrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
905 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
906 
907 	endCommandBuffer(vkd, cmdBuffer);
908 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
909 
910 	// Invalidate alloc and check destination buffer.
911 	auto& dstBufferAlloc = dstBuffer.getAllocation();
912 	invalidateAlloc(vkd, device, dstBufferAlloc);
913 
914 	decltype(srcValues) results (srcValues.size());
915 	deMemcpy(results.data(), dstBufferAlloc.getHostPtr(), de::dataSize(srcValues));
916 
917 	for (size_t valueIdx = 0; valueIdx < srcValues.size(); ++valueIdx)
918 	{
919 		const auto& orig	= srcValues[valueIdx];
920 		const auto& res		= results[valueIdx];
921 
922 		if (orig != res)
923 		{
924 			std::ostringstream msg;
925 			msg << "Unexpected value found in destination buffer at position " << valueIdx << " (found=" << res << " expected=" << orig << ")";
926 			TCU_FAIL(msg.str());
927 		}
928 	}
929 
930 	return tcu::TestStatus::pass("Pass");
931 }
932 
iterateCompute(void)933 tcu::TestStatus DynamicStateComputeInstance::iterateCompute (void)
934 {
935 	const auto&	vki			= m_context.getInstanceInterface();
936 	const auto	phyDev		= m_context.getPhysicalDevice();
937 	auto&		devHelper	= getDeviceHelper(m_context, m_params.states.at(0));
938 	const auto&	vkd			= devHelper.getDeviceInterface();
939 	const auto	device		= devHelper.getDevice();
940 	const auto	qIndex		= devHelper.getQueueFamilyIndex();
941 	const auto	queue		= devHelper.getQueue();
942 	auto&		alloc		= devHelper.getAllocator();
943 
944 	const auto	cmdPool			= makeCommandPool(vkd, device, qIndex);
945 	const auto	cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
946 	const auto	cmdBuffer		= cmdBufferPtr.get();
947 
948 	DescriptorSetLayoutBuilder setLayoutBuilder;
949 	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
950 	const auto	setLayout		= setLayoutBuilder.build(vkd, device);
951 
952 	// Push constants.
953 	const deUint32	pcSize		= static_cast<deUint32>(sizeof(deUint32));
954 	const auto		pcRange		= makePushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize);
955 
956 	// Pipeline.
957 	const VkPipelineLayoutCreateInfo layoutInfo =
958 	{
959 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//	VkStructureType					sType;
960 		nullptr,										//	const void*						pNext;
961 		0u,												//	VkPipelineLayoutCreateFlags		flags;
962 		1u,												//	deUint32						setLayoutCount;
963 		&setLayout.get(),								//	const VkDescriptorSetLayout*	pSetLayouts;
964 		1u,												//	deUint32						pushConstantRangeCount;
965 		&pcRange,										//	const VkPushConstantRange*		pPushConstantRanges;
966 	};
967 	const auto pipelineLayout = createPipelineLayout(vkd, device, &layoutInfo);
968 
969 	const auto shaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);
970 
971 	const VkPipelineShaderStageCreateInfo shaderStageInfo =
972 	{
973 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
974 		nullptr,												//	const void*							pNext;
975 		0u,														//	VkPipelineShaderStageCreateFlags	flags;
976 		VK_SHADER_STAGE_COMPUTE_BIT,							//	VkShaderStageFlagBits				stage;
977 		shaderModule.get(),										//	VkShaderModule						module;
978 		"main",													//	const char*							pName;
979 		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
980 	};
981 
982 	const VkComputePipelineCreateInfo pipelineInfo =
983 	{
984 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	//	VkStructureType					sType;
985 		nullptr,										//	const void*						pNext;
986 		0u,												//	VkPipelineCreateFlags			flags;
987 		shaderStageInfo,								//	VkPipelineShaderStageCreateInfo	stage;
988 		pipelineLayout.get(),							//	VkPipelineLayout				layout;
989 		DE_NULL,										//	VkPipeline						basePipelineHandle;
990 		0,												//	deInt32							basePipelineIndex;
991 	};
992 	const auto pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);
993 
994 	DE_ASSERT(!m_params.states.empty());
995 
996 	// Output buffer with one value per state.
997 	std::vector<deUint32>	bufferData			(m_params.states.size(), 0u);
998 	const auto				dataSize			(de::dataSize(bufferData));
999 	const auto				outputBufferSize	= de::roundUp(static_cast<VkDeviceSize>(dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
1000 	const auto				bufferCreateInfo	= makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1001 
1002 	BufferWithMemory		outputBuffer		(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
1003 	auto&					outputBufferAlloc	= outputBuffer.getAllocation();
1004 	auto					outputBufferPtr		= outputBufferAlloc.getHostPtr();
1005 
1006 	deMemcpy(outputBufferPtr, bufferData.data(), dataSize);
1007 	flushAlloc(vkd, device, outputBufferAlloc);
1008 
1009 	// Descriptor set.
1010 	DescriptorPoolBuilder poolBuilder;
1011 	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1012 	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1013 
1014 	const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
1015 
1016 	const auto bufferInfo = makeDescriptorBufferInfo(outputBuffer.get(), 0ull, outputBufferSize);
1017 	DescriptorSetUpdateBuilder updateBuilder;
1018 	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
1019 	updateBuilder.update(vkd, device);
1020 
1021 	// Record and submit.
1022 	beginCommandBuffer(vkd, cmdBuffer);
1023 
1024 	// We need to preserve dynamic state data until the command buffer has run.
1025 	std::vector<de::MovePtr<DynamicStateData>> statesData;
1026 
1027 	for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
1028 	{
1029 		// Objects needed to set the dynamic state.
1030 		const auto&	state		= m_params.states[stateIdx];
1031 		const auto	stateInfo	= getDynamicStateInfo(state);
1032 		statesData.push_back(getDynamicStateData(m_context, device, state));
1033 
1034 		if (m_params.whenToSet == WhenToSet::BEFORE)
1035 			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
1036 
1037 		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
1038 		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1039 		{
1040 			// Each state will write to a different buffer position.
1041 			const deUint32 pcData = static_cast<deUint32>(stateIdx);
1042 			vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize, &pcData);
1043 		}
1044 		vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
1045 
1046 		if (m_params.whenToSet == WhenToSet::AFTER)
1047 			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
1048 	}
1049 
1050 	// Barrier to read buffer contents.
1051 	const auto barrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1052 	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);
1053 
1054 	endCommandBuffer(vkd, cmdBuffer);
1055 	submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1056 
1057 	// Read and verify buffer contents.
1058 	invalidateAlloc(vkd, device, outputBufferAlloc);
1059 	deMemcpy(bufferData.data(), outputBufferPtr, dataSize);
1060 
1061 	for (size_t idx = 0u; idx < bufferData.size(); ++idx)
1062 	{
1063 		if (bufferData[idx] != 1u)
1064 		{
1065 			std::ostringstream msg;
1066 			msg << "Unexpected value found at buffer position " << idx << ": " << bufferData[idx];
1067 			TCU_FAIL(msg.str());
1068 		}
1069 	}
1070 
1071 	return tcu::TestStatus::pass("Pass");
1072 }
1073 
getDynamicStateBriefName(VkDynamicState state)1074 std::string getDynamicStateBriefName (VkDynamicState state)
1075 {
1076 	const auto fullName		= de::toString(state);
1077 	const auto prefixLen	= strlen("VK_DYNAMIC_STATE_");
1078 
1079 	return de::toLower(fullName.substr(prefixLen));
1080 }
1081 
1082 } // anonymous
1083 
createDynamicStateComputeTests(tcu::TestContext & testCtx)1084 tcu::TestCaseGroup* createDynamicStateComputeTests (tcu::TestContext& testCtx)
1085 {
1086 	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
1087 
1088 	GroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "compute_transfer", "Dynamic state mixed with compute and transfer operations"));
1089 
1090 	const struct
1091 	{
1092 		OperType	operationType;
1093 		const char*	name;
1094 	} operations[] =
1095 	{
1096 		{	OperType::COMPUTE,	"compute"	},
1097 		{	OperType::TRANSFER,	"transfer"	},
1098 	};
1099 
1100 	const struct
1101 	{
1102 		WhenToSet	when;
1103 		const char*	name;
1104 	} moments[] =
1105 	{
1106 		{	WhenToSet::BEFORE,	"before"	},
1107 		{	WhenToSet::AFTER,	"after"		},
1108 	};
1109 
1110 	// Tests with a single dynamic state.
1111 	{
1112 		GroupPtr singleStateGroup(new tcu::TestCaseGroup(testCtx, "single", "Tests using a single dynamic state"));
1113 
1114 		for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
1115 		{
1116 			GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));
1117 
1118 			for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
1119 			{
1120 				const auto	state		= dynamicStateList[stateIdx];
1121 				const auto	stateName	= getDynamicStateBriefName(state);
1122 
1123 				GroupPtr stateGroup(new tcu::TestCaseGroup(testCtx, stateName.c_str(), ""));
1124 
1125 				for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
1126 				{
1127 					const TestParams testParams =
1128 					{
1129 						operations[operIdx].operationType,		//	OperType					operationType;
1130 						moments[momentIdx].when,				//	WhenToSet					whenToSet;
1131 						std::vector<VkDynamicState>(1, state),	//	std::vector<VkDynamicState>	state;
1132 					};
1133 
1134 					stateGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
1135 				}
1136 
1137 				operationGroup->addChild(stateGroup.release());
1138 			}
1139 
1140 			singleStateGroup->addChild(operationGroup.release());
1141 		}
1142 
1143 		mainGroup->addChild(singleStateGroup.release());
1144 	}
1145 
1146 	// A few tests with several dynamic states.
1147 	{
1148 		GroupPtr multiStateGroup(new tcu::TestCaseGroup(testCtx, "multi", "Tests using multiple dynamic states"));
1149 
1150 		for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
1151 		{
1152 			GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));
1153 
1154 			for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
1155 			{
1156 				TestParams testParams =
1157 				{
1158 					operations[operIdx].operationType,	//	OperType					operationType;
1159 					moments[momentIdx].when,			//	WhenToSet					whenToSet;
1160 					std::vector<VkDynamicState>(),		//	std::vector<VkDynamicState>	states;
1161 				};
1162 
1163 				// Use the basic states so as not to introduce extra requirements.
1164 				for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
1165 				{
1166 					testParams.states.push_back(dynamicStateList[stateIdx]);
1167 					if (dynamicStateList[stateIdx] == VK_DYNAMIC_STATE_STENCIL_REFERENCE)
1168 						break;
1169 				}
1170 
1171 				operationGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
1172 			}
1173 
1174 			multiStateGroup->addChild(operationGroup.release());
1175 		}
1176 
1177 		mainGroup->addChild(multiStateGroup.release());
1178 	}
1179 
1180 	return mainGroup.release();
1181 }
1182 
cleanupDevice()1183 void cleanupDevice()
1184 {
1185 	g_shadingRateDeviceHelper.reset(nullptr);
1186 	g_contextDeviceHelper.reset(nullptr);
1187 }
1188 
1189 } // DynamicState
1190 } // vkt
1191