yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Jay KwakCheck the available VK extensions before using CoopVec APIs in GFX (#6849)591affaf7

master
28.2 KiB864 linesraw
1// vk-util.cpp
2#include "vk-util.h"
3
4#include "core/slang-math.h"
5
6#include <stdio.h>
7#include <stdlib.h>
8
9namespace gfx
10{
11
12/* static */ VkFormat VulkanUtil::getVkFormat(Format format)
13{
14    switch (format)
15    {
16    case Format::R32G32B32A32_TYPELESS:
17        return VK_FORMAT_R32G32B32A32_SFLOAT;
18    case Format::R32G32B32_TYPELESS:
19        return VK_FORMAT_R32G32B32_SFLOAT;
20    case Format::R32G32_TYPELESS:
21        return VK_FORMAT_R32G32_SFLOAT;
22    case Format::R32_TYPELESS:
23        return VK_FORMAT_R32_SFLOAT;
24
25    case Format::R16G16B16A16_TYPELESS:
26        return VK_FORMAT_R16G16B16A16_SFLOAT;
27    case Format::R16G16_TYPELESS:
28        return VK_FORMAT_R16G16_SFLOAT;
29    case Format::R16_TYPELESS:
30        return VK_FORMAT_R16_SFLOAT;
31
32    case Format::R8G8B8A8_TYPELESS:
33        return VK_FORMAT_R8G8B8A8_UNORM;
34    case Format::R8G8_TYPELESS:
35        return VK_FORMAT_R8G8_UNORM;
36    case Format::R8_TYPELESS:
37        return VK_FORMAT_R8_UNORM;
38    case Format::B8G8R8A8_TYPELESS:
39        return VK_FORMAT_B8G8R8A8_UNORM;
40
41    case Format::R64_UINT:
42        return VK_FORMAT_R64_UINT;
43
44    case Format::R32G32B32A32_FLOAT:
45        return VK_FORMAT_R32G32B32A32_SFLOAT;
46    case Format::R32G32B32_FLOAT:
47        return VK_FORMAT_R32G32B32_SFLOAT;
48    case Format::R32G32_FLOAT:
49        return VK_FORMAT_R32G32_SFLOAT;
50    case Format::R32_FLOAT:
51        return VK_FORMAT_R32_SFLOAT;
52
53    case Format::R16G16B16A16_FLOAT:
54        return VK_FORMAT_R16G16B16A16_SFLOAT;
55    case Format::R16G16_FLOAT:
56        return VK_FORMAT_R16G16_SFLOAT;
57    case Format::R16_FLOAT:
58        return VK_FORMAT_R16_SFLOAT;
59
60    case Format::R32G32B32A32_UINT:
61        return VK_FORMAT_R32G32B32A32_UINT;
62    case Format::R32G32B32_UINT:
63        return VK_FORMAT_R32G32B32_UINT;
64    case Format::R32G32_UINT:
65        return VK_FORMAT_R32G32_UINT;
66    case Format::R32_UINT:
67        return VK_FORMAT_R32_UINT;
68
69    case Format::R16G16B16A16_UINT:
70        return VK_FORMAT_R16G16B16A16_UINT;
71    case Format::R16G16_UINT:
72        return VK_FORMAT_R16G16_UINT;
73    case Format::R16_UINT:
74        return VK_FORMAT_R16_UINT;
75
76    case Format::R8G8B8A8_UINT:
77        return VK_FORMAT_R8G8B8A8_UINT;
78    case Format::R8G8_UINT:
79        return VK_FORMAT_R8G8_UINT;
80    case Format::R8_UINT:
81        return VK_FORMAT_R8_UINT;
82
83    case Format::R64_SINT:
84        return VK_FORMAT_R64_SINT;
85
86    case Format::R32G32B32A32_SINT:
87        return VK_FORMAT_R32G32B32A32_SINT;
88    case Format::R32G32B32_SINT:
89        return VK_FORMAT_R32G32B32_SINT;
90    case Format::R32G32_SINT:
91        return VK_FORMAT_R32G32_SINT;
92    case Format::R32_SINT:
93        return VK_FORMAT_R32_SINT;
94
95    case Format::R16G16B16A16_SINT:
96        return VK_FORMAT_R16G16B16A16_SINT;
97    case Format::R16G16_SINT:
98        return VK_FORMAT_R16G16_SINT;
99    case Format::R16_SINT:
100        return VK_FORMAT_R16_SINT;
101
102    case Format::R8G8B8A8_SINT:
103        return VK_FORMAT_R8G8B8A8_SINT;
104    case Format::R8G8_SINT:
105        return VK_FORMAT_R8G8_SINT;
106    case Format::R8_SINT:
107        return VK_FORMAT_R8_SINT;
108
109    case Format::R16G16B16A16_UNORM:
110        return VK_FORMAT_R16G16B16A16_UNORM;
111    case Format::R16G16_UNORM:
112        return VK_FORMAT_R16G16_UNORM;
113    case Format::R16_UNORM:
114        return VK_FORMAT_R16_UNORM;
115
116    case Format::R8G8B8A8_UNORM:
117        return VK_FORMAT_R8G8B8A8_UNORM;
118    case Format::R8G8B8A8_UNORM_SRGB:
119        return VK_FORMAT_R8G8B8A8_SRGB;
120    case Format::R8G8_UNORM:
121        return VK_FORMAT_R8G8_UNORM;
122    case Format::R8_UNORM:
123        return VK_FORMAT_R8_UNORM;
124    case Format::B8G8R8A8_UNORM:
125        return VK_FORMAT_B8G8R8A8_UNORM;
126    case Format::B8G8R8A8_UNORM_SRGB:
127        return VK_FORMAT_B8G8R8A8_SRGB;
128    case Format::B8G8R8X8_UNORM:
129        return VK_FORMAT_B8G8R8A8_UNORM;
130    case Format::B8G8R8X8_UNORM_SRGB:
131        return VK_FORMAT_B8G8R8A8_SRGB;
132
133    case Format::R16G16B16A16_SNORM:
134        return VK_FORMAT_R16G16B16A16_SNORM;
135    case Format::R16G16_SNORM:
136        return VK_FORMAT_R16G16_SNORM;
137    case Format::R16_SNORM:
138        return VK_FORMAT_R16_SNORM;
139
140    case Format::R8G8B8A8_SNORM:
141        return VK_FORMAT_R8G8B8A8_SNORM;
142    case Format::R8G8_SNORM:
143        return VK_FORMAT_R8G8_SNORM;
144    case Format::R8_SNORM:
145        return VK_FORMAT_R8_SNORM;
146
147    case Format::D32_FLOAT:
148        return VK_FORMAT_D32_SFLOAT;
149    case Format::D16_UNORM:
150        return VK_FORMAT_D16_UNORM;
151    case Format::D32_FLOAT_S8_UINT:
152        return VK_FORMAT_D32_SFLOAT_S8_UINT;
153    case Format::R32_FLOAT_X32_TYPELESS:
154        return VK_FORMAT_R32_SFLOAT;
155
156    case Format::B4G4R4A4_UNORM:
157        return VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT;
158    case Format::B5G6R5_UNORM:
159        return VK_FORMAT_R5G6B5_UNORM_PACK16;
160    case Format::B5G5R5A1_UNORM:
161        return VK_FORMAT_A1R5G5B5_UNORM_PACK16;
162
163    case Format::R9G9B9E5_SHAREDEXP:
164        return VK_FORMAT_E5B9G9R9_UFLOAT_PACK32;
165    case Format::R10G10B10A2_TYPELESS:
166        return VK_FORMAT_A2B10G10R10_UINT_PACK32;
167    case Format::R10G10B10A2_UINT:
168        return VK_FORMAT_A2B10G10R10_UINT_PACK32;
169    case Format::R10G10B10A2_UNORM:
170        return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
171    case Format::R11G11B10_FLOAT:
172        return VK_FORMAT_B10G11R11_UFLOAT_PACK32;
173
174    case Format::BC1_UNORM:
175        return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
176    case Format::BC1_UNORM_SRGB:
177        return VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
178    case Format::BC2_UNORM:
179        return VK_FORMAT_BC2_UNORM_BLOCK;
180    case Format::BC2_UNORM_SRGB:
181        return VK_FORMAT_BC2_SRGB_BLOCK;
182    case Format::BC3_UNORM:
183        return VK_FORMAT_BC3_UNORM_BLOCK;
184    case Format::BC3_UNORM_SRGB:
185        return VK_FORMAT_BC3_SRGB_BLOCK;
186    case Format::BC4_UNORM:
187        return VK_FORMAT_BC4_UNORM_BLOCK;
188    case Format::BC4_SNORM:
189        return VK_FORMAT_BC4_SNORM_BLOCK;
190    case Format::BC5_UNORM:
191        return VK_FORMAT_BC5_UNORM_BLOCK;
192    case Format::BC5_SNORM:
193        return VK_FORMAT_BC5_SNORM_BLOCK;
194    case Format::BC6H_UF16:
195        return VK_FORMAT_BC6H_UFLOAT_BLOCK;
196    case Format::BC6H_SF16:
197        return VK_FORMAT_BC6H_SFLOAT_BLOCK;
198    case Format::BC7_UNORM:
199        return VK_FORMAT_BC7_UNORM_BLOCK;
200    case Format::BC7_UNORM_SRGB:
201        return VK_FORMAT_BC7_SRGB_BLOCK;
202
203    default:
204        return VK_FORMAT_UNDEFINED;
205    }
206}
207
208VkImageAspectFlags VulkanUtil::getAspectMask(TextureAspect aspect, VkFormat format)
209{
210    switch (aspect)
211    {
212    case TextureAspect::Default:
213        switch (format)
214        {
215        case VK_FORMAT_D16_UNORM_S8_UINT:
216        case VK_FORMAT_D24_UNORM_S8_UINT:
217        case VK_FORMAT_D32_SFLOAT_S8_UINT:
218            return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
219        case VK_FORMAT_D16_UNORM:
220        case VK_FORMAT_D32_SFLOAT:
221        case VK_FORMAT_X8_D24_UNORM_PACK32:
222            return VK_IMAGE_ASPECT_DEPTH_BIT;
223        case VK_FORMAT_S8_UINT:
224            return VK_IMAGE_ASPECT_STENCIL_BIT;
225        default:
226            return VK_IMAGE_ASPECT_COLOR_BIT;
227        }
228    case TextureAspect::Color:
229        return VK_IMAGE_ASPECT_COLOR_BIT;
230    case TextureAspect::Depth:
231        return VK_IMAGE_ASPECT_DEPTH_BIT;
232    case TextureAspect::DepthStencil:
233        return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
234    case TextureAspect::Stencil:
235        return VK_IMAGE_ASPECT_STENCIL_BIT;
236    case TextureAspect::Plane0:
237        return VK_IMAGE_ASPECT_PLANE_0_BIT;
238    case TextureAspect::Plane1:
239        return VK_IMAGE_ASPECT_PLANE_1_BIT;
240
241    case TextureAspect::Plane2:
242        return VK_IMAGE_ASPECT_PLANE_2_BIT;
243
244    case TextureAspect::MetaData:
245        return VK_IMAGE_ASPECT_METADATA_BIT;
246    default:
247        SLANG_UNREACHABLE("getAspectMask");
248        return 0;
249    }
250}
251
252/* static */ SlangResult VulkanUtil::toSlangResult(VkResult res)
253{
254    return (res == VK_SUCCESS) ? SLANG_OK : SLANG_FAIL;
255}
256
257VkShaderStageFlags VulkanUtil::getShaderStage(SlangStage stage)
258{
259    switch (stage)
260    {
261    case SLANG_STAGE_ANY_HIT:
262        return VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
263    case SLANG_STAGE_CALLABLE:
264        return VK_SHADER_STAGE_CALLABLE_BIT_KHR;
265    case SLANG_STAGE_CLOSEST_HIT:
266        return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
267    case SLANG_STAGE_COMPUTE:
268        return VK_SHADER_STAGE_COMPUTE_BIT;
269    case SLANG_STAGE_DOMAIN:
270        return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
271    case SLANG_STAGE_FRAGMENT:
272        return VK_SHADER_STAGE_FRAGMENT_BIT;
273    case SLANG_STAGE_GEOMETRY:
274        return VK_SHADER_STAGE_GEOMETRY_BIT;
275    case SLANG_STAGE_HULL:
276        return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
277    case SLANG_STAGE_INTERSECTION:
278        return VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
279    case SLANG_STAGE_MISS:
280        return VK_SHADER_STAGE_MISS_BIT_KHR;
281    case SLANG_STAGE_RAY_GENERATION:
282        return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
283    case SLANG_STAGE_VERTEX:
284        return VK_SHADER_STAGE_VERTEX_BIT;
285    case SLANG_STAGE_MESH:
286        return VK_SHADER_STAGE_MESH_BIT_EXT;
287    case SLANG_STAGE_AMPLIFICATION:
288        return VK_SHADER_STAGE_TASK_BIT_EXT;
289    default:
290        assert(!"unsupported stage.");
291        return VkShaderStageFlags(-1);
292    }
293}
294
295VkImageLayout VulkanUtil::getImageLayoutFromState(ResourceState state)
296{
297    switch (state)
298    {
299    case ResourceState::ShaderResource:
300    case ResourceState::PixelShaderResource:
301    case ResourceState::NonPixelShaderResource:
302        return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
303    case ResourceState::UnorderedAccess:
304    case ResourceState::General:
305        return VK_IMAGE_LAYOUT_GENERAL;
306    case ResourceState::Present:
307        return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
308    case ResourceState::CopySource:
309        return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
310    case ResourceState::CopyDestination:
311        return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
312    case ResourceState::RenderTarget:
313        return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
314    case ResourceState::DepthWrite:
315        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
316    case ResourceState::DepthRead:
317        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
318    case ResourceState::ResolveSource:
319        return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
320    case ResourceState::ResolveDestination:
321        return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
322    default:
323        return VK_IMAGE_LAYOUT_UNDEFINED;
324    }
325    return VkImageLayout();
326}
327
328VkSampleCountFlagBits VulkanUtil::translateSampleCount(uint32_t sampleCount)
329{
330    switch (sampleCount)
331    {
332    case 1:
333        return VK_SAMPLE_COUNT_1_BIT;
334    case 2:
335        return VK_SAMPLE_COUNT_2_BIT;
336    case 4:
337        return VK_SAMPLE_COUNT_4_BIT;
338    case 8:
339        return VK_SAMPLE_COUNT_8_BIT;
340    case 16:
341        return VK_SAMPLE_COUNT_16_BIT;
342    case 32:
343        return VK_SAMPLE_COUNT_32_BIT;
344    case 64:
345        return VK_SAMPLE_COUNT_64_BIT;
346    default:
347        assert(!"Unsupported sample count");
348        return VK_SAMPLE_COUNT_1_BIT;
349    }
350}
351
352VkCullModeFlags VulkanUtil::translateCullMode(CullMode cullMode)
353{
354    switch (cullMode)
355    {
356    case CullMode::None:
357        return VK_CULL_MODE_NONE;
358    case CullMode::Front:
359        return VK_CULL_MODE_FRONT_BIT;
360    case CullMode::Back:
361        return VK_CULL_MODE_BACK_BIT;
362    default:
363        assert(!"Unsupported cull mode");
364        return VK_CULL_MODE_NONE;
365    }
366}
367
368VkFrontFace VulkanUtil::translateFrontFaceMode(FrontFaceMode frontFaceMode)
369{
370    switch (frontFaceMode)
371    {
372    case FrontFaceMode::CounterClockwise:
373        return VK_FRONT_FACE_COUNTER_CLOCKWISE;
374    case FrontFaceMode::Clockwise:
375        return VK_FRONT_FACE_CLOCKWISE;
376    default:
377        assert(!"Unsupported front face mode");
378        return VK_FRONT_FACE_CLOCKWISE;
379    }
380}
381
382VkPolygonMode VulkanUtil::translateFillMode(FillMode fillMode)
383{
384    switch (fillMode)
385    {
386    case FillMode::Solid:
387        return VK_POLYGON_MODE_FILL;
388    case FillMode::Wireframe:
389        return VK_POLYGON_MODE_LINE;
390    default:
391        assert(!"Unsupported fill mode");
392        return VK_POLYGON_MODE_FILL;
393    }
394}
395
396VkBlendFactor VulkanUtil::translateBlendFactor(BlendFactor blendFactor)
397{
398    switch (blendFactor)
399    {
400    case BlendFactor::Zero:
401        return VK_BLEND_FACTOR_ZERO;
402    case BlendFactor::One:
403        return VK_BLEND_FACTOR_ONE;
404    case BlendFactor::SrcColor:
405        return VK_BLEND_FACTOR_SRC_COLOR;
406    case BlendFactor::InvSrcColor:
407        return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
408    case BlendFactor::SrcAlpha:
409        return VK_BLEND_FACTOR_SRC_ALPHA;
410    case BlendFactor::InvSrcAlpha:
411        return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
412    case BlendFactor::DestAlpha:
413        return VK_BLEND_FACTOR_DST_ALPHA;
414    case BlendFactor::InvDestAlpha:
415        return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
416    case BlendFactor::DestColor:
417        return VK_BLEND_FACTOR_DST_COLOR;
418    case BlendFactor::InvDestColor:
419        return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
420    case BlendFactor::SrcAlphaSaturate:
421        return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
422    case BlendFactor::BlendColor:
423        return VK_BLEND_FACTOR_CONSTANT_COLOR;
424    case BlendFactor::InvBlendColor:
425        return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
426    case BlendFactor::SecondarySrcColor:
427        return VK_BLEND_FACTOR_SRC1_COLOR;
428    case BlendFactor::InvSecondarySrcColor:
429        return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
430    case BlendFactor::SecondarySrcAlpha:
431        return VK_BLEND_FACTOR_SRC1_ALPHA;
432    case BlendFactor::InvSecondarySrcAlpha:
433        return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
434
435    default:
436        assert(!"Unsupported blend factor");
437        return VK_BLEND_FACTOR_ONE;
438    }
439}
440
441VkBlendOp VulkanUtil::translateBlendOp(BlendOp op)
442{
443    switch (op)
444    {
445    case BlendOp::Add:
446        return VK_BLEND_OP_ADD;
447    case BlendOp::Subtract:
448        return VK_BLEND_OP_SUBTRACT;
449    case BlendOp::ReverseSubtract:
450        return VK_BLEND_OP_REVERSE_SUBTRACT;
451    case BlendOp::Min:
452        return VK_BLEND_OP_MIN;
453    case BlendOp::Max:
454        return VK_BLEND_OP_MAX;
455    default:
456        assert(!"Unsupported blend op");
457        return VK_BLEND_OP_ADD;
458    }
459}
460
461VkPrimitiveTopology VulkanUtil::translatePrimitiveTypeToListTopology(PrimitiveType primitiveType)
462{
463    switch (primitiveType)
464    {
465    case PrimitiveType::Point:
466        return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
467    case PrimitiveType::Line:
468        return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
469    case PrimitiveType::Triangle:
470        return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
471    case PrimitiveType::Patch:
472        return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
473    default:
474        assert(!"unknown topology type.");
475        return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
476    }
477}
478
479VkStencilOp VulkanUtil::translateStencilOp(StencilOp op)
480{
481    switch (op)
482    {
483    case StencilOp::DecrementSaturate:
484        return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
485    case StencilOp::DecrementWrap:
486        return VK_STENCIL_OP_DECREMENT_AND_WRAP;
487    case StencilOp::IncrementSaturate:
488        return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
489    case StencilOp::IncrementWrap:
490        return VK_STENCIL_OP_INCREMENT_AND_WRAP;
491    case StencilOp::Invert:
492        return VK_STENCIL_OP_INVERT;
493    case StencilOp::Keep:
494        return VK_STENCIL_OP_KEEP;
495    case StencilOp::Replace:
496        return VK_STENCIL_OP_REPLACE;
497    case StencilOp::Zero:
498        return VK_STENCIL_OP_ZERO;
499    default:
500        return VK_STENCIL_OP_KEEP;
501    }
502}
503
504VkFilter VulkanUtil::translateFilterMode(TextureFilteringMode mode)
505{
506    switch (mode)
507    {
508    default:
509        return VkFilter(0);
510
511#define CASE(SRC, DST)              \
512    case TextureFilteringMode::SRC: \
513        return VK_FILTER_##DST
514
515        CASE(Point, NEAREST);
516        CASE(Linear, LINEAR);
517
518#undef CASE
519    }
520}
521
522VkSamplerMipmapMode VulkanUtil::translateMipFilterMode(TextureFilteringMode mode)
523{
524    switch (mode)
525    {
526    default:
527        return VkSamplerMipmapMode(0);
528
529#define CASE(SRC, DST)              \
530    case TextureFilteringMode::SRC: \
531        return VK_SAMPLER_MIPMAP_MODE_##DST
532
533        CASE(Point, NEAREST);
534        CASE(Linear, LINEAR);
535
536#undef CASE
537    }
538}
539
540VkSamplerAddressMode VulkanUtil::translateAddressingMode(TextureAddressingMode mode)
541{
542    switch (mode)
543    {
544    default:
545        return VkSamplerAddressMode(0);
546
547#define CASE(SRC, DST)               \
548    case TextureAddressingMode::SRC: \
549        return VK_SAMPLER_ADDRESS_MODE_##DST
550
551        CASE(Wrap, REPEAT);
552        CASE(ClampToEdge, CLAMP_TO_EDGE);
553        CASE(ClampToBorder, CLAMP_TO_BORDER);
554        CASE(MirrorRepeat, MIRRORED_REPEAT);
555        CASE(MirrorOnce, MIRROR_CLAMP_TO_EDGE);
556
557#undef CASE
558    }
559}
560
561VkCompareOp VulkanUtil::translateComparisonFunc(ComparisonFunc func)
562{
563    switch (func)
564    {
565    default:
566        // TODO: need to report failures
567        return VK_COMPARE_OP_ALWAYS;
568
569#define CASE(FROM, TO)         \
570    case ComparisonFunc::FROM: \
571        return VK_COMPARE_OP_##TO
572
573        CASE(Never, NEVER);
574        CASE(Less, LESS);
575        CASE(Equal, EQUAL);
576        CASE(LessEqual, LESS_OR_EQUAL);
577        CASE(Greater, GREATER);
578        CASE(NotEqual, NOT_EQUAL);
579        CASE(GreaterEqual, GREATER_OR_EQUAL);
580        CASE(Always, ALWAYS);
581#undef CASE
582    }
583}
584
585VkStencilOpState VulkanUtil::translateStencilState(DepthStencilOpDesc desc)
586{
587    VkStencilOpState rs;
588    rs.compareMask = 0xFF;
589    rs.compareOp = translateComparisonFunc(desc.stencilFunc);
590    rs.depthFailOp = translateStencilOp(desc.stencilDepthFailOp);
591    rs.failOp = translateStencilOp(desc.stencilFailOp);
592    rs.passOp = translateStencilOp(desc.stencilPassOp);
593    rs.reference = 0;
594    rs.writeMask = 0xFF;
595    return rs;
596}
597
598VkSamplerReductionMode VulkanUtil::translateReductionOp(TextureReductionOp op)
599{
600    switch (op)
601    {
602    case gfx::TextureReductionOp::Minimum:
603        return VK_SAMPLER_REDUCTION_MODE_MIN;
604    case gfx::TextureReductionOp::Maximum:
605        return VK_SAMPLER_REDUCTION_MODE_MAX;
606    default:
607        return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE;
608    }
609}
610
611CooperativeVectorComponentType VulkanUtil::translateCooperativeVectorComponentType(
612    VkComponentTypeKHR type)
613{
614    switch (type)
615    {
616    case VK_COMPONENT_TYPE_FLOAT16_KHR:
617        return CooperativeVectorComponentType::Float16;
618    case VK_COMPONENT_TYPE_FLOAT32_KHR:
619        return CooperativeVectorComponentType::Float32;
620    case VK_COMPONENT_TYPE_FLOAT64_KHR:
621        return CooperativeVectorComponentType::Float64;
622    case VK_COMPONENT_TYPE_SINT8_KHR:
623        return CooperativeVectorComponentType::SInt8;
624    case VK_COMPONENT_TYPE_SINT16_KHR:
625        return CooperativeVectorComponentType::SInt16;
626    case VK_COMPONENT_TYPE_SINT32_KHR:
627        return CooperativeVectorComponentType::SInt32;
628    case VK_COMPONENT_TYPE_SINT64_KHR:
629        return CooperativeVectorComponentType::SInt64;
630    case VK_COMPONENT_TYPE_UINT8_KHR:
631        return CooperativeVectorComponentType::UInt8;
632    case VK_COMPONENT_TYPE_UINT16_KHR:
633        return CooperativeVectorComponentType::UInt16;
634    case VK_COMPONENT_TYPE_UINT32_KHR:
635        return CooperativeVectorComponentType::UInt32;
636    case VK_COMPONENT_TYPE_UINT64_KHR:
637        return CooperativeVectorComponentType::UInt64;
638    case VK_COMPONENT_TYPE_SINT8_PACKED_NV:
639        return CooperativeVectorComponentType::SInt8Packed;
640    case VK_COMPONENT_TYPE_UINT8_PACKED_NV:
641        return CooperativeVectorComponentType::UInt8Packed;
642    case VK_COMPONENT_TYPE_FLOAT_E4M3_NV:
643        return CooperativeVectorComponentType::FloatE4M3;
644    case VK_COMPONENT_TYPE_FLOAT_E5M2_NV:
645        return CooperativeVectorComponentType::FloatE5M2;
646    default:
647        return CooperativeVectorComponentType(0);
648    }
649}
650
651/* static */ Slang::Result VulkanUtil::handleFail(VkResult res)
652{
653    if (res != VK_SUCCESS)
654    {
655        assert(!"Vulkan returned a failure");
656    }
657    return toSlangResult(res);
658}
659
660/* static */ void VulkanUtil::checkFail(VkResult res)
661{
662    assert(res != VK_SUCCESS);
663    assert(!"Vulkan check failed");
664}
665
666/* static */ VkPrimitiveTopology VulkanUtil::getVkPrimitiveTopology(PrimitiveTopology topology)
667{
668    switch (topology)
669    {
670    case PrimitiveTopology::LineList:
671        return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
672    case PrimitiveTopology::LineStrip:
673        return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
674    case PrimitiveTopology::TriangleList:
675        return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
676    case PrimitiveTopology::TriangleStrip:
677        return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
678    case PrimitiveTopology::PointList:
679        return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
680    default:
681        break;
682    }
683    assert(!"Unknown topology");
684    return VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
685}
686
687VkImageLayout VulkanUtil::mapResourceStateToLayout(ResourceState state)
688{
689    switch (state)
690    {
691    case ResourceState::Undefined:
692        return VK_IMAGE_LAYOUT_UNDEFINED;
693    case ResourceState::ShaderResource:
694    case ResourceState::PixelShaderResource:
695    case ResourceState::NonPixelShaderResource:
696        return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
697    case ResourceState::UnorderedAccess:
698        return VK_IMAGE_LAYOUT_GENERAL;
699    case ResourceState::RenderTarget:
700        return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
701    case ResourceState::DepthRead:
702        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
703    case ResourceState::DepthWrite:
704        return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
705    case ResourceState::Present:
706        return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
707    case ResourceState::CopySource:
708        return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
709    case ResourceState::CopyDestination:
710        return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
711    case ResourceState::ResolveSource:
712        return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
713    case ResourceState::ResolveDestination:
714        return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
715    default:
716        return VK_IMAGE_LAYOUT_UNDEFINED;
717    }
718}
719
720Result AccelerationStructureBuildGeometryInfoBuilder::build(
721    const IAccelerationStructure::BuildInputs& buildInputs,
722    IDebugCallback* debugCallback)
723{
724    buildInfo.dstAccelerationStructure = VK_NULL_HANDLE;
725    switch (buildInputs.kind)
726    {
727    case IAccelerationStructure::Kind::BottomLevel:
728        buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR;
729        break;
730    case IAccelerationStructure::Kind::TopLevel:
731        buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR;
732        break;
733    default:
734        debugCallback->handleMessage(
735            DebugMessageType::Error,
736            DebugMessageSource::Layer,
737            "invalid value of IAccelerationStructure::Kind encountered in buildInputs.kind");
738        return SLANG_E_INVALID_ARG;
739    }
740    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::PerformUpdate)
741    {
742        buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR;
743    }
744    else
745    {
746        buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR;
747    }
748    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::AllowCompaction)
749    {
750        buildInfo.flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
751    }
752    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::AllowUpdate)
753    {
754        buildInfo.flags |= VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR;
755    }
756    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::MinimizeMemory)
757    {
758        buildInfo.flags |= VK_BUILD_ACCELERATION_STRUCTURE_LOW_MEMORY_BIT_KHR;
759    }
760    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::PreferFastBuild)
761    {
762        buildInfo.flags |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR;
763    }
764    if (buildInputs.flags & IAccelerationStructure::BuildFlags::Enum::PreferFastTrace)
765    {
766        buildInfo.flags |= VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR;
767    }
768    if (buildInputs.kind == IAccelerationStructure::Kind::BottomLevel)
769    {
770        m_geometryInfos.setCount(buildInputs.descCount);
771        primitiveCounts.setCount(buildInputs.descCount);
772        memset(
773            m_geometryInfos.getBuffer(),
774            0,
775            sizeof(VkAccelerationStructureGeometryKHR) * buildInputs.descCount);
776        for (int i = 0; i < buildInputs.descCount; i++)
777        {
778            auto& geomDesc = buildInputs.geometryDescs[i];
779            m_geometryInfos[i].sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR;
780            if (geomDesc.flags & IAccelerationStructure::GeometryFlags::NoDuplicateAnyHitInvocation)
781            {
782                m_geometryInfos[i].flags |= VK_GEOMETRY_NO_DUPLICATE_ANY_HIT_INVOCATION_BIT_KHR;
783            }
784            else if (geomDesc.flags & IAccelerationStructure::GeometryFlags::Opaque)
785            {
786                m_geometryInfos[i].flags |= VK_GEOMETRY_OPAQUE_BIT_KHR;
787            }
788            auto& vkGeomData = m_geometryInfos[i].geometry;
789            switch (geomDesc.type)
790            {
791            case IAccelerationStructure::GeometryType::Triangles:
792                m_geometryInfos[i].geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR;
793                vkGeomData.triangles.sType =
794                    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR;
795                vkGeomData.triangles.vertexFormat =
796                    VulkanUtil::getVkFormat(geomDesc.content.triangles.vertexFormat);
797                vkGeomData.triangles.vertexData.deviceAddress =
798                    geomDesc.content.triangles.vertexData;
799                vkGeomData.triangles.vertexStride = geomDesc.content.triangles.vertexStride;
800                vkGeomData.triangles.maxVertex = geomDesc.content.triangles.vertexCount - 1;
801                switch (geomDesc.content.triangles.indexFormat)
802                {
803                case Format::R32_UINT:
804                    vkGeomData.triangles.indexType = VK_INDEX_TYPE_UINT32;
805                    break;
806                case Format::R16_UINT:
807                    vkGeomData.triangles.indexType = VK_INDEX_TYPE_UINT16;
808                    break;
809                case Format::Unknown:
810                    vkGeomData.triangles.indexType = VK_INDEX_TYPE_NONE_KHR;
811                    break;
812                default:
813                    debugCallback->handleMessage(
814                        DebugMessageType::Error,
815                        DebugMessageSource::Layer,
816                        "unsupported value of Format encountered in "
817                        "GeometryDesc::content.triangles.indexFormat");
818                    return SLANG_E_INVALID_ARG;
819                }
820                vkGeomData.triangles.indexData.deviceAddress = geomDesc.content.triangles.indexData;
821                vkGeomData.triangles.transformData.deviceAddress =
822                    geomDesc.content.triangles.transform3x4;
823                primitiveCounts[i] = Slang::Math::Max(
824                                         geomDesc.content.triangles.vertexCount,
825                                         geomDesc.content.triangles.indexCount) /
826                                     3;
827                break;
828            case IAccelerationStructure::GeometryType::ProcedurePrimitives:
829                m_geometryInfos[i].geometryType = VK_GEOMETRY_TYPE_AABBS_KHR;
830                vkGeomData.aabbs.sType =
831                    VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR;
832                vkGeomData.aabbs.data.deviceAddress = geomDesc.content.proceduralAABBs.data;
833                vkGeomData.aabbs.stride = geomDesc.content.proceduralAABBs.stride;
834                primitiveCounts[i] =
835                    (uint32_t)buildInputs.geometryDescs[i].content.proceduralAABBs.count;
836                break;
837            default:
838                debugCallback->handleMessage(
839                    DebugMessageType::Error,
840                    DebugMessageSource::Layer,
841                    "invalid value of IAccelerationStructure::GeometryType encountered in "
842                    "buildInputs.geometryDescs");
843                return SLANG_E_INVALID_ARG;
844            }
845        }
846        buildInfo.geometryCount = buildInputs.descCount;
847        buildInfo.pGeometries = m_geometryInfos.getBuffer();
848    }
849    else
850    {
851        m_vkInstanceInfo.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR;
852        m_vkInstanceInfo.geometry.instances.sType =
853            VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR;
854        m_vkInstanceInfo.geometry.instances.arrayOfPointers = 0;
855        m_vkInstanceInfo.geometry.instances.data.deviceAddress = buildInputs.instanceDescs;
856        buildInfo.pGeometries = &m_vkInstanceInfo;
857        buildInfo.geometryCount = 1;
858        primitiveCounts.setCount(1);
859        primitiveCounts[0] = buildInputs.descCount;
860    }
861    return SLANG_OK;
862}
863
864} // namespace gfx