1/*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 LunarG, Inc.
6 * Copyright (c) 2023 Nintendo
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 Utilities for vertex buffers.
23 *//*--------------------------------------------------------------------*/
24
25#include "vktShaderObjectCreateUtil.hpp"
26#include "vktTestCase.hpp"
27
28namespace vk
29{
30
31std::string getShaderName (vk::VkShaderStageFlagBits stage)
32{
33	switch (stage)
34	{
35	case vk::VK_SHADER_STAGE_VERTEX_BIT:					return "vert";
36	case vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:		return "tesc";
37	case vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:	return "tese";
38	case vk::VK_SHADER_STAGE_GEOMETRY_BIT:					return "geom";
39	case vk::VK_SHADER_STAGE_FRAGMENT_BIT:					return "frag";
40	case vk::VK_SHADER_STAGE_COMPUTE_BIT:					return "comp";
41	case vk::VK_SHADER_STAGE_MESH_BIT_EXT:					return "mesh";
42	case vk::VK_SHADER_STAGE_TASK_BIT_EXT:					return "task";
43	default:
44		DE_ASSERT(false);
45		break;
46	}
47	return {};
48}
49
50vk::VkShaderStageFlags getShaderObjectNextStages (vk::VkShaderStageFlagBits shaderStage, bool tessellationShaderFeature, bool geometryShaderFeature)
51{
52	if (shaderStage == vk::VK_SHADER_STAGE_VERTEX_BIT)
53	{
54		vk::VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
55		if (tessellationShaderFeature)
56			flags |= vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
57		if (geometryShaderFeature)
58			flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
59		return flags;
60	}
61	else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
62	{
63		return vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
64	}
65	else if (shaderStage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
66	{
67		vk::VkShaderStageFlags flags = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
68		if (geometryShaderFeature)
69			flags |= vk::VK_SHADER_STAGE_GEOMETRY_BIT;
70		return flags;
71	}
72	else if (shaderStage == vk::VK_SHADER_STAGE_GEOMETRY_BIT)
73	{
74		return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
75	}
76	else if (shaderStage == vk::VK_SHADER_STAGE_TASK_BIT_EXT)
77	{
78		return vk::VK_SHADER_STAGE_MESH_BIT_EXT;
79	}
80	else if (shaderStage == vk::VK_SHADER_STAGE_MESH_BIT_EXT)
81	{
82		return vk::VK_SHADER_STAGE_FRAGMENT_BIT;
83	}
84	return 0;
85}
86
87Move<VkShaderEXT> createShaderFromBinary (const DeviceInterface& vk, VkDevice device, vk::VkShaderStageFlagBits shaderStage, size_t codeSize, const void* pCode, bool tessellationShaderFeature, bool geometryShaderFeature, vk::VkDescriptorSetLayout descriptorSetLayout)
88{
89	vk::VkShaderCreateInfoEXT		pCreateInfo =
90	{
91		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,								// VkStructureType				sType;
92		DE_NULL,																	// const void*					pNext;
93		0u,																			// VkShaderCreateFlagsEXT		flags;
94		shaderStage,																// VkShaderStageFlagBits		stage;
95		getShaderObjectNextStages(shaderStage, tessellationShaderFeature, geometryShaderFeature),	// VkShaderStageFlags			nextStage;
96		vk::VK_SHADER_CODE_TYPE_BINARY_EXT,											// VkShaderCodeTypeEXT			codeType;
97		codeSize,																	// size_t						codeSize;
98		pCode,																		// const void*					pCode;
99		"main",																		// const char*					pName;
100		(descriptorSetLayout != VK_NULL_HANDLE) ? 1u : 0u,							// uint32_t						setLayoutCount;
101		(descriptorSetLayout != VK_NULL_HANDLE) ? &descriptorSetLayout : DE_NULL,	// VkDescriptorSetLayout*		pSetLayouts;
102		0u,																			// uint32_t						pushConstantRangeCount;
103		DE_NULL,																	// const VkPushConstantRange*	pPushConstantRanges;
104		DE_NULL,																	// const VkSpecializationInfo*	pSpecializationInfo;
105	};
106
107	return createShader(vk, device, pCreateInfo);
108}
109
110Move<VkShaderEXT> createShader (const DeviceInterface& vk, VkDevice device, const vk::VkShaderCreateInfoEXT& shaderCreateInfo)
111{
112	VkShaderEXT object = VK_NULL_HANDLE;
113	VK_CHECK(vk.createShadersEXT(device, 1u, &shaderCreateInfo, DE_NULL, &object));
114	return Move<VkShaderEXT>(check<VkShaderEXT>(object), Deleter<VkShaderEXT>(vk, device, DE_NULL));
115}
116
117void addBasicShaderObjectShaders (vk::SourceCollections& programCollection)
118{
119	std::stringstream vert;
120	std::stringstream geom;
121	std::stringstream tesc;
122	std::stringstream tese;
123	std::stringstream frag;
124	std::stringstream comp;
125
126	vert
127		<< "#version 450\n"
128		<< "void main() {\n"
129		<< "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
130		<< "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
131		<< "}\n";
132
133	tesc
134		<< "#version 450\n"
135		<< "\n"
136		<< "layout(vertices = 4) out;\n"
137		<< "\n"
138		<< "void main (void)\n"
139		<< "{\n"
140		<< "    if (gl_InvocationID == 0) {\n"
141		<< "		gl_TessLevelInner[0] = 1.0;\n"
142		<< "		gl_TessLevelInner[1] = 1.0;\n"
143		<< "		gl_TessLevelOuter[0] = 1.0;\n"
144		<< "		gl_TessLevelOuter[1] = 1.0;\n"
145		<< "		gl_TessLevelOuter[2] = 1.0;\n"
146		<< "		gl_TessLevelOuter[3] = 1.0;\n"
147		<< "	}\n"
148		<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
149		<< "}\n";
150
151	tese
152		<< "#version 450\n"
153		<< "\n"
154		<< "layout(quads, equal_spacing) in;\n"
155		<< "\n"
156		<< "void main (void)\n"
157		<< "{\n"
158		<< "	float u = gl_TessCoord.x;\n"
159		<< "	float v = gl_TessCoord.y;\n"
160		<< "	float omu = 1.0f - u;\n"
161		<< "	float omv = 1.0f - v;\n"
162		<< "	gl_Position = omu * omv * gl_in[0].gl_Position + u * omv * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position + omu * v * gl_in[1].gl_Position;\n"
163		<< "	gl_Position.x *= 1.5f;\n"
164		<< "}\n";
165
166	geom
167		<< "#version 450\n"
168		<< "layout(triangles) in;\n"
169		<< "layout(triangle_strip, max_vertices = 4) out;\n"
170		<< "\n"
171		<< "void main(void)\n"
172		<< "{\n"
173		<< "    gl_Position = gl_in[0].gl_Position;\n"
174		<< "	gl_Position.y *= 1.5f;\n"
175		<< "    gl_Position.z = 0.5f;\n"
176		<< "    EmitVertex();\n"
177		<< "    gl_Position = gl_in[1].gl_Position;\n"
178		<< "	gl_Position.y *= 1.5f;\n"
179		<< "    gl_Position.z = 0.5f;\n"
180		<< "    EmitVertex();\n"
181		<< "    gl_Position = gl_in[2].gl_Position;\n"
182		<< "	gl_Position.y *= 1.5f;\n"
183		<< "    gl_Position.z = 0.5f;\n"
184		<< "    EmitVertex();\n"
185		<< "    EndPrimitive();\n"
186		<< "}\n";
187
188	frag
189		<< "#version 450\n"
190		<< "layout (location=0) out vec4 outColor;\n"
191		<< "void main() {\n"
192		<< "    outColor = vec4(1.0f);\n"
193		<< "}\n";
194
195	comp
196		<< "#version 450\n"
197		<< "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n"
198		<< "layout(binding = 0) buffer Output {\n"
199		<< "    uint values[16];\n"
200		<< "} buffer_out;\n\n"
201		<< "void main() {\n"
202		<< "    buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n"
203		<< "}\n";
204
205	programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
206	programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
207	programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
208	programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
209	programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
210	programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
211}
212
213vk::VkShaderCreateInfoEXT makeShaderCreateInfo (vk::VkShaderStageFlagBits stage, const vk::ProgramBinary& programBinary, bool tessellationShaderFeature, bool geometryShaderFeature, const vk::VkDescriptorSetLayout* descriptorSetLayout)
214{
215	vk::VkShaderCreateInfoEXT shaderCreateInfo =
216	{
217		vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT,						// VkStructureType				sType;
218		DE_NULL,															// const void*					pNext;
219		0u,																	// VkShaderCreateFlagsEXT		flags;
220		stage,																// VkShaderStageFlagBits		stage;
221		vk::getShaderObjectNextStages(stage, tessellationShaderFeature, geometryShaderFeature),	// VkShaderStageFlags			nextStage;
222		vk::VK_SHADER_CODE_TYPE_SPIRV_EXT,									// VkShaderCodeTypeEXT			codeType;
223		programBinary.getSize(),											// size_t						codeSize;
224		programBinary.getBinary(),											// const void*					pCode;
225		"main",																// const char*					pName;
226		(descriptorSetLayout != DE_NULL) ? 1u : 0u,							// uint32_t						setLayoutCount;
227		(descriptorSetLayout != DE_NULL) ? descriptorSetLayout : DE_NULL,	// VkDescriptorSetLayout*		pSetLayouts;
228		0u,																	// uint32_t						pushConstantRangeCount;
229		DE_NULL,															// const VkPushConstantRange*	pPushConstantRanges;
230		DE_NULL,															// const VkSpecializationInfo*	pSpecializationInfo;
231	};
232
233	return shaderCreateInfo;
234}
235
236bool extensionEnabled(const std::vector<std::string>& deviceExtensions, const std::string& ext)
237{
238	return std::find(deviceExtensions.begin(), deviceExtensions.end(), ext) != deviceExtensions.end();
239}
240
241void setDefaultShaderObjectDynamicStates (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, const std::vector<std::string>& deviceExtensions, vk::VkPrimitiveTopology topology, bool meshShader, bool setViewport)
242{
243	vk::VkViewport viewport = { 0, 0, 32, 32, 0.0f, 1.0f, };
244	if (setViewport)
245		vk.cmdSetViewport(cmdBuffer, 0u, 1u, &viewport);
246	vk.cmdSetViewportWithCount(cmdBuffer, 1u, &viewport);
247	vk::VkRect2D scissor = { { 0, 0, }, { 32, 32, }, };
248	if (setViewport)
249		vk.cmdSetScissor(cmdBuffer, 0u, 1u, &scissor);
250	vk.cmdSetScissorWithCount(cmdBuffer, 1u, &scissor);
251	vk.cmdSetLineWidth(cmdBuffer, 1.0f);
252	vk.cmdSetDepthBias(cmdBuffer, 1.0f, 1.0f, 1.0f);
253	float blendConstants[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
254	vk.cmdSetBlendConstants(cmdBuffer, blendConstants);
255	vk.cmdSetDepthBounds(cmdBuffer, 0.0f, 1.0f);
256	vk.cmdSetStencilCompareMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFFFFFFF);
257	vk.cmdSetStencilWriteMask(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFFFFFFF);
258	vk.cmdSetStencilReference(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFFFFFFF);
259	vk.cmdBindVertexBuffers2(cmdBuffer, 0, 0, DE_NULL, DE_NULL, DE_NULL, DE_NULL);
260	vk.cmdSetCullMode(cmdBuffer, vk::VK_CULL_MODE_NONE);
261	vk.cmdSetDepthBoundsTestEnable(cmdBuffer, VK_FALSE);
262	vk.cmdSetDepthCompareOp(cmdBuffer, vk::VK_COMPARE_OP_NEVER);
263	vk.cmdSetDepthTestEnable(cmdBuffer, VK_FALSE);
264	vk.cmdSetDepthWriteEnable(cmdBuffer, VK_FALSE);
265	vk.cmdSetFrontFace(cmdBuffer, vk::VK_FRONT_FACE_CLOCKWISE);
266	if (!meshShader)
267		vk.cmdSetPrimitiveTopology(cmdBuffer, topology);
268	vk.cmdSetStencilOp(cmdBuffer, vk::VK_STENCIL_FACE_FRONT_AND_BACK, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_NEVER);
269	vk.cmdSetStencilTestEnable(cmdBuffer, VK_FALSE);
270	vk.cmdSetDepthBiasEnable(cmdBuffer, VK_FALSE);
271	if (!meshShader)
272		vk.cmdSetPrimitiveRestartEnable(cmdBuffer, VK_FALSE);
273	vk.cmdSetRasterizerDiscardEnable(cmdBuffer, VK_FALSE);
274	if (!meshShader && (extensionEnabled(deviceExtensions, "VK_EXT_shader_object") || extensionEnabled(deviceExtensions, "VK_EXT_vertex_input_dynamic_state")))
275		vk.cmdSetVertexInputEXT(cmdBuffer, 0u, DE_NULL, 0u, DE_NULL);
276	vk.cmdSetLogicOpEXT(cmdBuffer, vk::VK_LOGIC_OP_AND);
277	if (!meshShader)
278		vk.cmdSetPatchControlPointsEXT(cmdBuffer, 4u);
279	vk.cmdSetTessellationDomainOriginEXT(cmdBuffer, vk::VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT);
280	vk.cmdSetDepthClampEnableEXT(cmdBuffer, VK_FALSE);
281	vk.cmdSetPolygonModeEXT(cmdBuffer, vk::VK_POLYGON_MODE_FILL);
282	vk.cmdSetRasterizationSamplesEXT(cmdBuffer, vk::VK_SAMPLE_COUNT_1_BIT);
283	vk::VkSampleMask sampleMask = 0xFFFFFFFF;
284	vk.cmdSetSampleMaskEXT(cmdBuffer, vk::VK_SAMPLE_COUNT_1_BIT, &sampleMask);
285	vk.cmdSetAlphaToCoverageEnableEXT(cmdBuffer, VK_FALSE);
286	vk.cmdSetAlphaToOneEnableEXT(cmdBuffer, VK_FALSE);
287	vk.cmdSetLogicOpEnableEXT(cmdBuffer, VK_FALSE);
288	vk::VkBool32 colorBlendEnable = VK_FALSE;
289	vk.cmdSetColorBlendEnableEXT(cmdBuffer, 0u, 1u, &colorBlendEnable);
290	vk::VkColorBlendEquationEXT		colorBlendEquation = {
291		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	srcColorBlendFactor;
292		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	dstColorBlendFactor;
293		vk::VK_BLEND_OP_ADD,			// VkBlendOp		colorBlendOp;
294		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	srcAlphaBlendFactor;
295		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor	dstAlphaBlendFactor;
296		vk::VK_BLEND_OP_ADD,			// VkBlendOp		alphaBlendOp;
297	};
298	vk.cmdSetColorBlendEquationEXT(cmdBuffer, 0u, 1u, &colorBlendEquation);
299	vk::VkColorComponentFlags		colorWriteMask = vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT |
300		vk::VK_COLOR_COMPONENT_B_BIT | vk::VK_COLOR_COMPONENT_A_BIT;
301	vk.cmdSetColorWriteMaskEXT(cmdBuffer, 0u, 1u, &colorWriteMask);
302	vk::VkExtent2D fragmentSize = { 1u, 1u };
303	vk::VkFragmentShadingRateCombinerOpKHR combinerOps[2] = { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR };
304	if (extensionEnabled(deviceExtensions, "VK_KHR_fragment_shading_rate"))
305		vk.cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, combinerOps);
306	if (extensionEnabled(deviceExtensions, "VK_EXT_transform_feedback"))
307		vk.cmdSetRasterizationStreamEXT(cmdBuffer, 0);
308	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization"))
309		vk.cmdSetConservativeRasterizationModeEXT(cmdBuffer, vk::VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT);
310	if (extensionEnabled(deviceExtensions, "VK_EXT_conservative_rasterization"))
311		vk.cmdSetExtraPrimitiveOverestimationSizeEXT(cmdBuffer, 0.0f);
312	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_enable"))
313		vk.cmdSetDepthClipEnableEXT(cmdBuffer, VK_FALSE);
314	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
315		vk.cmdSetSampleLocationsEnableEXT(cmdBuffer, VK_FALSE);
316	VkSampleLocationEXT sampleLocation = { 0.5f, 0.5f };
317	const vk::VkSampleLocationsInfoEXT sampleLocations =
318	{
319		vk::VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,	// VkStructureType               sType;
320		DE_NULL,											// const void*                   pNext;
321		VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits         sampleLocationsPerPixel;
322		{ 1u, 1u },											// VkExtent2D                    sampleLocationGridSize;
323		1,													// uint32_t                      sampleLocationsCount;
324		&sampleLocation,									// const VkSampleLocationEXT*    pSampleLocations;
325	};
326	if (extensionEnabled(deviceExtensions, "VK_EXT_sample_locations"))
327		vk.cmdSetSampleLocationsEXT(cmdBuffer, &sampleLocations);
328	vk::VkColorBlendAdvancedEXT colorBlendAdvanced;
329	colorBlendAdvanced.advancedBlendOp = vk::VK_BLEND_OP_SRC_EXT;
330	colorBlendAdvanced.srcPremultiplied = VK_FALSE;
331	colorBlendAdvanced.dstPremultiplied = VK_FALSE;
332	colorBlendAdvanced.blendOverlap = vk::VK_BLEND_OVERLAP_UNCORRELATED_EXT;
333	colorBlendAdvanced.clampResults = VK_FALSE;
334	if (extensionEnabled(deviceExtensions, "VK_EXT_blend_operation_advanced"))
335		vk.cmdSetColorBlendAdvancedEXT(cmdBuffer, 0, 1, &colorBlendAdvanced);
336	if (extensionEnabled(deviceExtensions, "VK_EXT_provoking_vertex"))
337		vk.cmdSetProvokingVertexModeEXT(cmdBuffer, vk::VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
338	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization"))
339		vk.cmdSetLineRasterizationModeEXT(cmdBuffer, vk::VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT);
340	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization"))
341		vk.cmdSetLineStippleEnableEXT(cmdBuffer, VK_FALSE);
342	if (extensionEnabled(deviceExtensions, "VK_EXT_line_rasterization"))
343		vk.cmdSetLineStippleEXT(cmdBuffer, 1u, 0x0F0F);
344	if (extensionEnabled(deviceExtensions, "VK_EXT_depth_clip_control"))
345		vk.cmdSetDepthClipNegativeOneToOneEXT(cmdBuffer, VK_FALSE);
346	VkBool32 colorWriteEnable = VK_TRUE;
347	if (extensionEnabled(deviceExtensions, "VK_EXT_color_write_enable"))
348		vk.cmdSetColorWriteEnableEXT(cmdBuffer, 1, &colorWriteEnable);
349	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
350		vk.cmdSetViewportWScalingEnableNV(cmdBuffer, VK_FALSE);
351	vk::VkViewportWScalingNV viewportWScaling = { 1.0f, 1.0f };
352	if (extensionEnabled(deviceExtensions, "VK_NV_clip_space_w_scaling"))
353		vk.cmdSetViewportWScalingNV(cmdBuffer, 0, 1, &viewportWScaling);
354	vk::VkViewportSwizzleNV viewportSwizzle;
355	viewportSwizzle.x = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV;
356	viewportSwizzle.y = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV;
357	viewportSwizzle.z = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV;
358	viewportSwizzle.w = VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV;
359	if (extensionEnabled(deviceExtensions, "VK_NV_viewport_swizzle"))
360		vk.cmdSetViewportSwizzleNV(cmdBuffer, 0, 1, &viewportSwizzle);
361	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color"))
362		vk.cmdSetCoverageToColorEnableNV(cmdBuffer, VK_FALSE);
363	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_coverage_to_color"))
364		vk.cmdSetCoverageToColorLocationNV(cmdBuffer, 0);
365	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples"))
366		vk.cmdSetCoverageModulationModeNV(cmdBuffer, vk::VK_COVERAGE_MODULATION_MODE_NONE_NV);
367	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples"))
368		vk.cmdSetCoverageModulationTableEnableNV(cmdBuffer, VK_FALSE);
369	float coverageModulationTable = 1.0f;
370	if (extensionEnabled(deviceExtensions, "VK_NV_framebuffer_mixed_samples"))
371		vk.cmdSetCoverageModulationTableNV(cmdBuffer, 1, &coverageModulationTable);
372	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
373		vk.cmdSetShadingRateImageEnableNV(cmdBuffer, VK_FALSE);
374	if (extensionEnabled(deviceExtensions, "VK_NV_coverage_reduction_mode"))
375		vk.cmdSetCoverageReductionModeNV(cmdBuffer, vk::VK_COVERAGE_REDUCTION_MODE_MERGE_NV);
376	if (extensionEnabled(deviceExtensions, "VK_NV_representative_fragment_test"))
377		vk.cmdSetRepresentativeFragmentTestEnableNV(cmdBuffer, VK_FALSE);
378	vk::VkBool32 scissorEnable = VK_FALSE;
379	if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
380		vk.cmdSetExclusiveScissorEnableNV(cmdBuffer, 0u, 1u, &scissorEnable);
381	if (extensionEnabled(deviceExtensions, "VK_NV_scissor_exclusive"))
382		vk.cmdSetExclusiveScissorNV(cmdBuffer, 0u, 1u, &scissor);
383	if (extensionEnabled(deviceExtensions, "VK_NV_fragment_shading_rate_enums"))
384		vk.cmdSetFragmentShadingRateEnumNV(cmdBuffer, vk::VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV, combinerOps);
385	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
386		vk.cmdSetDiscardRectangleEnableEXT(cmdBuffer, VK_FALSE);
387	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
388		vk.cmdSetDiscardRectangleEXT(cmdBuffer, 0u, 1u, &scissor);
389	if (extensionEnabled(deviceExtensions, "VK_EXT_discard_rectangles"))
390		vk.cmdSetDiscardRectangleModeEXT(cmdBuffer, vk::VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT);
391	if (extensionEnabled(deviceExtensions, "VK_NV_shading_rate_image"))
392		vk.cmdSetShadingRateImageEnableNV(cmdBuffer, VK_FALSE);
393	if (extensionEnabled(deviceExtensions, "VK_EXT_attachment_feedback_loop_dynamic_state"))
394		vk.cmdSetAttachmentFeedbackLoopEnableEXT(cmdBuffer, 0u);
395}
396
397void bindGraphicsShaders (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkShaderEXT vertShader, vk::VkShaderEXT tescShader, vk::VkShaderEXT teseShader, vk::VkShaderEXT geomShader, vk::VkShaderEXT fragShader, bool taskShaderSupported, bool meshShaderSupported)
398{
399	vk::VkShaderStageFlagBits stages[] = {
400			vk::VK_SHADER_STAGE_VERTEX_BIT,
401			vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
402			vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
403			vk::VK_SHADER_STAGE_GEOMETRY_BIT,
404			vk::VK_SHADER_STAGE_FRAGMENT_BIT,
405	};
406	vk::VkShaderEXT shaders[] = {
407		vertShader,
408		tescShader,
409		teseShader,
410		geomShader,
411		fragShader,
412	};
413	vk.cmdBindShadersEXT(cmdBuffer, 5u, stages, shaders);
414	if (taskShaderSupported) {
415		vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
416		vk::VkShaderEXT shader = VK_NULL_HANDLE;
417		vk.cmdBindShadersEXT(cmdBuffer, 1u, &stage, &shader);
418	}
419	if (meshShaderSupported) {
420		vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
421		vk::VkShaderEXT shader = VK_NULL_HANDLE;
422		vk.cmdBindShadersEXT(cmdBuffer, 1u, &stage, &shader);
423	}
424}
425
426void bindComputeShader (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkShaderEXT compShader)
427{
428	vk::VkShaderStageFlagBits stage = vk::VK_SHADER_STAGE_COMPUTE_BIT;
429	vk.cmdBindShadersEXT(cmdBuffer, 1, &stage, &compShader);
430}
431
432void bindNullTaskMeshShaders (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkPhysicalDeviceMeshShaderFeaturesEXT meshShaderFeatures)
433{
434	vk::VkShaderEXT shader = VK_NULL_HANDLE;
435	vk::VkShaderStageFlagBits taskStage = vk::VK_SHADER_STAGE_TASK_BIT_EXT;
436	vk::VkShaderStageFlagBits meshStage = vk::VK_SHADER_STAGE_MESH_BIT_EXT;
437	if (meshShaderFeatures.taskShader) {
438		vk.cmdBindShadersEXT(cmdBuffer, 1u, &taskStage, &shader);
439	}
440	if (meshShaderFeatures.meshShader) {
441		vk.cmdBindShadersEXT(cmdBuffer, 1u, &meshStage, &shader);
442	}
443}
444
445void bindNullRasterizationShaders (const vk::DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, vk::VkPhysicalDeviceFeatures features)
446{
447	vk::VkShaderEXT shader = VK_NULL_HANDLE;
448	vk::VkShaderStageFlagBits vertStage = vk::VK_SHADER_STAGE_VERTEX_BIT;
449	vk::VkShaderStageFlagBits tescStage = vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
450	vk::VkShaderStageFlagBits teseStage = vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
451	vk::VkShaderStageFlagBits geomStage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
452	vk.cmdBindShadersEXT(cmdBuffer, 1u, &vertStage, &shader);
453	if (features.tessellationShader) {
454		vk.cmdBindShadersEXT(cmdBuffer, 1u, &tescStage, &shader);
455		vk.cmdBindShadersEXT(cmdBuffer, 1u, &teseStage, &shader);
456	}
457	if (features.geometryShader) {
458		vk.cmdBindShadersEXT(cmdBuffer, 1u, &geomStage, &shader);
459	}
460}
461
462} // vk
463