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