yum-mirror/slang

Making it easier to work with shaders

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

Gangzheng TongEnable Windows full debug testsuite in CI (#7085)8f20632a0

master
17.1 KiB495 linesraw
1// render.cpp
2#include "../../source/core/slang-blob.h"
3#include "../../source/core/slang-math.h"
4#include "debug-layer/debug-device.h"
5#include "open-gl/render-gl.h"
6#include "renderer-shared.h"
7
8#include <cstring>
9
10namespace gfx
11{
12using namespace Slang;
13
14Result SLANG_MCALL createD3D11Device(const IDevice::Desc* desc, IDevice** outDevice);
15Result SLANG_MCALL createD3D12Device(const IDevice::Desc* desc, IDevice** outDevice);
16Result SLANG_MCALL createVKDevice(const IDevice::Desc* desc, IDevice** outDevice);
17Result SLANG_MCALL createMetalDevice(const IDevice::Desc* desc, IDevice** outDevice);
18Result SLANG_MCALL createCUDADevice(const IDevice::Desc* desc, IDevice** outDevice);
19Result SLANG_MCALL createCPUDevice(const IDevice::Desc* desc, IDevice** outDevice);
20
21Result SLANG_MCALL getD3D11Adapters(List<AdapterInfo>& outAdapters);
22Result SLANG_MCALL getD3D12Adapters(List<AdapterInfo>& outAdapters);
23Result SLANG_MCALL getVKAdapters(List<AdapterInfo>& outAdapters);
24Result SLANG_MCALL getMetalAdapters(List<AdapterInfo>& outAdapters);
25Result SLANG_MCALL getCUDAAdapters(List<AdapterInfo>& outAdapters);
26
27Result SLANG_MCALL reportD3DLiveObjects();
28
29// Enable debug layer (validation layer) by default for DEBUG build
30#if _DEBUG
31static bool debugLayerEnabled = true;
32#else
33static bool debugLayerEnabled = false;
34#endif
35
36bool isGfxDebugLayerEnabled()
37{
38    return debugLayerEnabled;
39}
40
41/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Global Renderer Functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
42
43#define GFX_FORMAT_SIZE(name, blockSizeInBytes, pixelsPerBlock) {blockSizeInBytes, pixelsPerBlock},
44
45static const uint32_t s_formatSizeInfo[][2] = {GFX_FORMAT(GFX_FORMAT_SIZE)};
46
47static bool _checkFormat()
48{
49    Index value = 0;
50    Index count = 0;
51
52    // Check the values are in the same order
53#define GFX_FORMAT_CHECK(name, blockSizeInBytes, pixelsPerblock) \
54    count += Index(Index(Format::name) == value++);
55    GFX_FORMAT(GFX_FORMAT_CHECK)
56
57    const bool r = (count == Index(Format::_Count));
58    SLANG_ASSERT(r);
59    return r;
60}
61
62// We don't make static because we will get a warning that it's unused
63static const bool _checkFormatResult = _checkFormat();
64
65struct FormatInfoMap
66{
67    FormatInfoMap()
68    {
69        // Set all to nothing initially
70        for (auto& info : m_infos)
71        {
72            info.channelCount = 0;
73            info.channelType = SLANG_SCALAR_TYPE_NONE;
74        }
75
76        set(Format::R32G32B32A32_TYPELESS, SLANG_SCALAR_TYPE_UINT32, 4);
77        set(Format::R32G32B32_TYPELESS, SLANG_SCALAR_TYPE_UINT32, 3);
78        set(Format::R32G32_TYPELESS, SLANG_SCALAR_TYPE_UINT32, 2);
79        set(Format::R32_TYPELESS, SLANG_SCALAR_TYPE_UINT32, 1);
80
81        set(Format::R16G16B16A16_TYPELESS, SLANG_SCALAR_TYPE_UINT16, 4);
82        set(Format::R16G16_TYPELESS, SLANG_SCALAR_TYPE_UINT16, 2);
83        set(Format::R16_TYPELESS, SLANG_SCALAR_TYPE_UINT16, 1);
84
85        set(Format::R8G8B8A8_TYPELESS, SLANG_SCALAR_TYPE_UINT8, 4);
86        set(Format::R8G8_TYPELESS, SLANG_SCALAR_TYPE_UINT8, 2);
87        set(Format::R8_TYPELESS, SLANG_SCALAR_TYPE_UINT8, 1);
88        set(Format::B8G8R8A8_TYPELESS, SLANG_SCALAR_TYPE_UINT8, 4);
89
90        set(Format::R32G32B32A32_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 4);
91        set(Format::R32G32B32_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 3);
92        set(Format::R32G32_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 2);
93        set(Format::R32_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 1);
94
95        set(Format::R16G16B16A16_FLOAT, SLANG_SCALAR_TYPE_FLOAT16, 4);
96        set(Format::R16G16_FLOAT, SLANG_SCALAR_TYPE_FLOAT16, 2);
97        set(Format::R16_FLOAT, SLANG_SCALAR_TYPE_FLOAT16, 1);
98
99        set(Format::R64_UINT, SLANG_SCALAR_TYPE_UINT64, 1);
100
101        set(Format::R32G32B32A32_UINT, SLANG_SCALAR_TYPE_UINT32, 4);
102        set(Format::R32G32B32_UINT, SLANG_SCALAR_TYPE_UINT32, 3);
103        set(Format::R32G32_UINT, SLANG_SCALAR_TYPE_UINT32, 2);
104        set(Format::R32_UINT, SLANG_SCALAR_TYPE_UINT32, 1);
105
106        set(Format::R16G16B16A16_UINT, SLANG_SCALAR_TYPE_UINT16, 4);
107        set(Format::R16G16_UINT, SLANG_SCALAR_TYPE_UINT16, 2);
108        set(Format::R16_UINT, SLANG_SCALAR_TYPE_UINT16, 1);
109
110        set(Format::R8G8B8A8_UINT, SLANG_SCALAR_TYPE_UINT8, 4);
111        set(Format::R8G8_UINT, SLANG_SCALAR_TYPE_UINT8, 2);
112        set(Format::R8_UINT, SLANG_SCALAR_TYPE_UINT8, 1);
113
114        set(Format::R64_SINT, SLANG_SCALAR_TYPE_INT64, 1);
115
116        set(Format::R32G32B32A32_SINT, SLANG_SCALAR_TYPE_INT32, 4);
117        set(Format::R32G32B32_SINT, SLANG_SCALAR_TYPE_INT32, 3);
118        set(Format::R32G32_SINT, SLANG_SCALAR_TYPE_INT32, 2);
119        set(Format::R32_SINT, SLANG_SCALAR_TYPE_INT32, 1);
120
121        set(Format::R16G16B16A16_SINT, SLANG_SCALAR_TYPE_INT16, 4);
122        set(Format::R16G16_SINT, SLANG_SCALAR_TYPE_INT16, 2);
123        set(Format::R16_SINT, SLANG_SCALAR_TYPE_INT16, 1);
124
125        set(Format::R8G8B8A8_SINT, SLANG_SCALAR_TYPE_INT8, 4);
126        set(Format::R8G8_SINT, SLANG_SCALAR_TYPE_INT8, 2);
127        set(Format::R8_SINT, SLANG_SCALAR_TYPE_INT8, 1);
128
129        set(Format::R16G16B16A16_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
130        set(Format::R16G16_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 2);
131        set(Format::R16_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 1);
132
133        set(Format::R8G8B8A8_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
134        set(Format::R8G8B8A8_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4);
135        set(Format::R8G8_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 2);
136        set(Format::R8_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 1);
137        set(Format::B8G8R8A8_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
138        set(Format::B8G8R8A8_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4);
139        set(Format::B8G8R8X8_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
140        set(Format::B8G8R8X8_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4);
141
142        set(Format::R16G16B16A16_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
143        set(Format::R16G16_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 2);
144        set(Format::R16_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 1);
145
146        set(Format::R8G8B8A8_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
147        set(Format::R8G8_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 2);
148        set(Format::R8_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 1);
149
150        set(Format::D32_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 1);
151        set(Format::D16_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 1);
152        set(Format::D32_FLOAT_S8_UINT, SLANG_SCALAR_TYPE_FLOAT32, 2);
153        set(Format::R32_FLOAT_X32_TYPELESS, SLANG_SCALAR_TYPE_FLOAT32, 2);
154
155        set(Format::B4G4R4A4_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
156        set(Format::B5G6R5_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 3);
157        set(Format::B5G5R5A1_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
158
159        set(Format::R9G9B9E5_SHAREDEXP, SLANG_SCALAR_TYPE_FLOAT32, 3);
160        set(Format::R10G10B10A2_TYPELESS, SLANG_SCALAR_TYPE_FLOAT32, 4);
161        set(Format::R10G10B10A2_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4);
162        set(Format::R10G10B10A2_UINT, SLANG_SCALAR_TYPE_UINT32, 4);
163        set(Format::R11G11B10_FLOAT, SLANG_SCALAR_TYPE_FLOAT32, 3);
164
165        set(Format::BC1_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
166        set(Format::BC1_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
167        set(Format::BC2_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
168        set(Format::BC2_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
169        set(Format::BC3_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
170        set(Format::BC3_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
171        set(Format::BC4_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 1, 4, 4);
172        set(Format::BC4_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 1, 4, 4);
173        set(Format::BC5_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 2, 4, 4);
174        set(Format::BC5_SNORM, SLANG_SCALAR_TYPE_FLOAT32, 2, 4, 4);
175        set(Format::BC6H_UF16, SLANG_SCALAR_TYPE_FLOAT32, 3, 4, 4);
176        set(Format::BC6H_SF16, SLANG_SCALAR_TYPE_FLOAT32, 3, 4, 4);
177        set(Format::BC7_UNORM, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
178        set(Format::BC7_UNORM_SRGB, SLANG_SCALAR_TYPE_FLOAT32, 4, 4, 4);
179    }
180
181    void set(
182        Format format,
183        SlangScalarType type,
184        Index channelCount,
185        uint32_t blockWidth = 1,
186        uint32_t blockHeight = 1)
187    {
188        FormatInfo& info = m_infos[Index(format)];
189        info.channelCount = uint8_t(channelCount);
190        info.channelType = uint8_t(type);
191
192        auto sizeInfo = s_formatSizeInfo[Index(format)];
193        info.blockSizeInBytes = sizeInfo[0];
194        info.pixelsPerBlock = sizeInfo[1];
195        info.blockWidth = blockWidth;
196        info.blockHeight = blockHeight;
197    }
198
199    const FormatInfo& get(Format format) const { return m_infos[Index(format)]; }
200
201    FormatInfo m_infos[Index(Format::_Count)];
202};
203
204static const FormatInfoMap s_formatInfoMap;
205
206static void _compileTimeAsserts()
207{
208    SLANG_COMPILE_TIME_ASSERT(SLANG_COUNT_OF(s_formatSizeInfo) == int(Format::_Count));
209}
210
211extern "C"
212{
213    SLANG_GFX_API bool SLANG_MCALL gfxIsCompressedFormat(Format format)
214    {
215        switch (format)
216        {
217        case Format::BC1_UNORM:
218        case Format::BC1_UNORM_SRGB:
219        case Format::BC2_UNORM:
220        case Format::BC2_UNORM_SRGB:
221        case Format::BC3_UNORM:
222        case Format::BC3_UNORM_SRGB:
223        case Format::BC4_UNORM:
224        case Format::BC4_SNORM:
225        case Format::BC5_UNORM:
226        case Format::BC5_SNORM:
227        case Format::BC6H_UF16:
228        case Format::BC6H_SF16:
229        case Format::BC7_UNORM:
230        case Format::BC7_UNORM_SRGB:
231            return true;
232        default:
233            return false;
234        }
235    }
236
237    SLANG_GFX_API bool SLANG_MCALL gfxIsTypelessFormat(Format format)
238    {
239        switch (format)
240        {
241        case Format::R32G32B32A32_TYPELESS:
242        case Format::R32G32B32_TYPELESS:
243        case Format::R32G32_TYPELESS:
244        case Format::R32_TYPELESS:
245        case Format::R16G16B16A16_TYPELESS:
246        case Format::R16G16_TYPELESS:
247        case Format::R16_TYPELESS:
248        case Format::R8G8B8A8_TYPELESS:
249        case Format::R8G8_TYPELESS:
250        case Format::R8_TYPELESS:
251        case Format::B8G8R8A8_TYPELESS:
252        case Format::R10G10B10A2_TYPELESS:
253            return true;
254        default:
255            return false;
256        }
257    }
258
259    SLANG_GFX_API SlangResult SLANG_MCALL gfxGetFormatInfo(Format format, FormatInfo* outInfo)
260    {
261        *outInfo = s_formatInfoMap.get(format);
262        return SLANG_OK;
263    }
264
265    SLANG_GFX_API SlangResult SLANG_MCALL
266    gfxGetAdapters(DeviceType type, ISlangBlob** outAdaptersBlob)
267    {
268        List<AdapterInfo> adapters;
269
270        switch (type)
271        {
272#if SLANG_ENABLE_DIRECTX
273        case DeviceType::DirectX11:
274            SLANG_RETURN_ON_FAIL(getD3D11Adapters(adapters));
275            break;
276        case DeviceType::DirectX12:
277            SLANG_RETURN_ON_FAIL(getD3D12Adapters(adapters));
278            break;
279#endif
280#if SLANG_WINDOWS_FAMILY
281        case DeviceType::OpenGl:
282            return SLANG_E_NOT_IMPLEMENTED;
283#endif
284#if SLANG_WINDOWS_FAMILY || SLANG_LINUX_FAMILY
285            // Assume no Vulkan or CUDA on MacOS or Cygwin
286        case DeviceType::Vulkan:
287            SLANG_RETURN_ON_FAIL(getVKAdapters(adapters));
288            break;
289        case DeviceType::CUDA:
290            SLANG_RETURN_ON_FAIL(getCUDAAdapters(adapters));
291            break;
292#endif
293#if SLANG_APPLE_FAMILY
294        case DeviceType::Vulkan:
295            SLANG_RETURN_ON_FAIL(getVKAdapters(adapters));
296            break;
297        case DeviceType::Metal:
298            SLANG_RETURN_ON_FAIL(getMetalAdapters(adapters));
299            break;
300#endif
301        case DeviceType::CPU:
302            return SLANG_E_NOT_IMPLEMENTED;
303        default:
304            return SLANG_E_INVALID_ARG;
305        }
306
307        auto adaptersBlob =
308            RawBlob::create(adapters.getBuffer(), adapters.getCount() * sizeof(AdapterInfo));
309        if (outAdaptersBlob)
310            returnComPtr(outAdaptersBlob, adaptersBlob);
311
312        return SLANG_OK;
313    }
314
315    SlangResult _createDevice(const IDevice::Desc* desc, IDevice** outDevice)
316    {
317        switch (desc->deviceType)
318        {
319#if SLANG_ENABLE_DIRECTX
320        case DeviceType::DirectX11:
321            {
322                return createD3D11Device(desc, outDevice);
323            }
324        case DeviceType::DirectX12:
325            {
326                return createD3D12Device(desc, outDevice);
327            }
328#endif
329#if SLANG_WINDOWS_FAMILY
330        case DeviceType::OpenGl:
331            {
332                return createGLDevice(desc, outDevice);
333            }
334        case DeviceType::Vulkan:
335            {
336                return createVKDevice(desc, outDevice);
337            }
338        case DeviceType::Default:
339            {
340                IDevice::Desc newDesc = *desc;
341                newDesc.deviceType = DeviceType::DirectX12;
342                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
343                    return SLANG_OK;
344                newDesc.deviceType = DeviceType::Vulkan;
345                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
346                    return SLANG_OK;
347                newDesc.deviceType = DeviceType::DirectX11;
348                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
349                    return SLANG_OK;
350                newDesc.deviceType = DeviceType::OpenGl;
351                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
352                    return SLANG_OK;
353                return SLANG_FAIL;
354            }
355            break;
356#elif SLANG_APPLE_FAMILY
357        case DeviceType::Vulkan:
358            {
359                return createVKDevice(desc, outDevice);
360            }
361        case DeviceType::Metal:
362            {
363                return createMetalDevice(desc, outDevice);
364            }
365        case DeviceType::Default:
366            {
367                IDevice::Desc newDesc = *desc;
368                newDesc.deviceType = DeviceType::Metal;
369                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
370                    return SLANG_OK;
371                newDesc.deviceType = DeviceType::Vulkan;
372                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
373                    return SLANG_OK;
374                return SLANG_FAIL;
375            }
376#elif SLANG_LINUX_FAMILY && !defined(__CYGWIN__)
377        case DeviceType::Vulkan:
378            {
379                return createVKDevice(desc, outDevice);
380            }
381        case DeviceType::Default:
382            {
383                IDevice::Desc newDesc = *desc;
384                newDesc.deviceType = DeviceType::Vulkan;
385                if (_createDevice(&newDesc, outDevice) == SLANG_OK)
386                    return SLANG_OK;
387                return SLANG_FAIL;
388            }
389#endif
390        case DeviceType::CUDA:
391            {
392                return createCUDADevice(desc, outDevice);
393            }
394        case DeviceType::CPU:
395            {
396                return createCPUDevice(desc, outDevice);
397            }
398            break;
399
400        default:
401            return SLANG_FAIL;
402        }
403    }
404
405    SLANG_GFX_API SlangResult SLANG_MCALL
406    gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice)
407    {
408        ComPtr<IDevice> innerDevice;
409        auto resultCode = _createDevice(desc, innerDevice.writeRef());
410        if (SLANG_FAILED(resultCode))
411            return resultCode;
412        if (!debugLayerEnabled)
413        {
414            returnComPtr(outDevice, innerDevice);
415            return resultCode;
416        }
417        RefPtr<debug::DebugDevice> debugDevice = new debug::DebugDevice();
418        debugDevice->baseObject = innerDevice;
419        returnComPtr(outDevice, debugDevice);
420        return resultCode;
421    }
422
423    SLANG_GFX_API SlangResult SLANG_MCALL gfxReportLiveObjects()
424    {
425#if SLANG_ENABLE_DIRECTX
426        SLANG_RETURN_ON_FAIL(reportD3DLiveObjects());
427#endif
428        return SLANG_OK;
429    }
430
431    SLANG_GFX_API SlangResult SLANG_MCALL gfxSetDebugCallback(IDebugCallback* callback)
432    {
433        _getDebugCallback() = callback;
434        return SLANG_OK;
435    }
436
437    SLANG_GFX_API void SLANG_MCALL gfxEnableDebugLayer(bool enable)
438    {
439        debugLayerEnabled = enable;
440    }
441
442    const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type)
443    {
444        switch (type)
445        {
446        case gfx::DeviceType::Unknown:
447            return "Unknown";
448        case gfx::DeviceType::Default:
449            return "Default";
450        case gfx::DeviceType::DirectX11:
451            return "DirectX11";
452        case gfx::DeviceType::DirectX12:
453            return "DirectX12";
454        case gfx::DeviceType::OpenGl:
455            return "OpenGL";
456        case gfx::DeviceType::Vulkan:
457            return "Vulkan";
458        case gfx::DeviceType::Metal:
459            return "Metal";
460        case gfx::DeviceType::CPU:
461            return "CPU";
462        case gfx::DeviceType::CUDA:
463            return "CUDA";
464        default:
465            return "?";
466        }
467    }
468
469
470    void SLANG_MCALL gfxGetIdentityProjection(ProjectionStyle style, float projMatrix[16])
471    {
472        switch (style)
473        {
474        case ProjectionStyle::DirectX:
475        case ProjectionStyle::OpenGl:
476            {
477                static const float kIdentity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
478                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
479                break;
480            }
481        case ProjectionStyle::Vulkan:
482            {
483                static const float kIdentity[] = {1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
484                ::memcpy(projMatrix, kIdentity, sizeof(kIdentity));
485                break;
486            }
487        default:
488            {
489                assert(!"Not handled");
490            }
491        }
492    }
493}
494
495} // namespace gfx