summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/core/slang-string.h2
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp144
-rw-r--r--tools/gfx/d3d12/render-d3d12.cpp151
-rw-r--r--tools/gfx/render-graphics-common.cpp2
-rw-r--r--tools/gfx/render.h1
-rw-r--r--tools/gfx/vulkan/render-vk.cpp1
6 files changed, 175 insertions, 126 deletions
diff --git a/source/core/slang-string.h b/source/core/slang-string.h
index 9f6eaafa7..cec4b0a09 100644
--- a/source/core/slang-string.h
+++ b/source/core/slang-string.h
@@ -72,7 +72,7 @@ namespace Slang
explicit UnownedStringSlice(char const* a) :
m_begin(a),
- m_end(a + strlen(a))
+ m_end(a ? a + strlen(a) : nullptr)
{}
UnownedStringSlice(char const* b, char const* e)
: m_begin(b)
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp
index 4ac90f47f..a2cf63a8f 100644
--- a/tools/gfx/d3d11/render-d3d11.cpp
+++ b/tools/gfx/d3d11/render-d3d11.cpp
@@ -692,6 +692,15 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
return SLANG_FAIL;
}
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice_ =
+ (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3dModule, "D3D11CreateDevice");
+ if (!D3D11CreateDevice_)
+ {
+ fprintf(stderr,
+ "error: failed load symbol 'D3D11CreateDevice'\n");
+ return SLANG_FAIL;
+ }
+
// Our swap chain uses RGBA8 with sRGB, with double buffering.
DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
@@ -773,20 +782,36 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
const int startFeatureIndex = (deviceCheckFlags & DeviceCheckFlag::UseFullFeatureLevel) ? 0 : 1;
const UINT deviceFlags = (deviceCheckFlags & DeviceCheckFlag::UseDebug) ? D3D11_CREATE_DEVICE_DEBUG : 0;
- res = D3D11CreateDeviceAndSwapChain_(
- adapter,
- driverType,
- nullptr, // software
- deviceFlags,
- &featureLevels[startFeatureIndex],
- totalNumFeatureLevels - startFeatureIndex,
- D3D11_SDK_VERSION,
- &swapChainDesc,
- m_swapChain.writeRef(),
- m_device.writeRef(),
- &featureLevel,
- m_immediateContext.writeRef());
-
+ if (windowHandle)
+ {
+ res = D3D11CreateDeviceAndSwapChain_(
+ adapter,
+ driverType,
+ nullptr, // software
+ deviceFlags,
+ &featureLevels[startFeatureIndex],
+ totalNumFeatureLevels - startFeatureIndex,
+ D3D11_SDK_VERSION,
+ &swapChainDesc,
+ m_swapChain.writeRef(),
+ m_device.writeRef(),
+ &featureLevel,
+ m_immediateContext.writeRef());
+ }
+ else
+ {
+ res = D3D11CreateDevice_(
+ adapter,
+ driverType,
+ nullptr,
+ deviceFlags,
+ &featureLevels[startFeatureIndex],
+ totalNumFeatureLevels - startFeatureIndex,
+ D3D11_SDK_VERSION,
+ m_device.writeRef(),
+ &featureLevel,
+ m_immediateContext.writeRef());
+ }
// Check if successfully constructed - if so we are done.
if (SLANG_SUCCEEDED(res))
{
@@ -799,7 +824,8 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
return res;
}
// Check we have a swap chain, context and device
- SLANG_ASSERT(m_immediateContext && m_swapChain && m_device);
+ SLANG_ASSERT(m_immediateContext && m_device);
+ SLANG_ASSERT(!windowHandle || m_swapChain);
}
// NVAPI
@@ -841,54 +867,55 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
static const IID kIID_ID3D11Texture2D = {
0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48,
0x95, 0x35, 0xd3, 0x4f, 0x9c };
-
- SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)m_backBufferTexture.writeRef()));
-
-// for (int i = 0; i < 8; i++)
+ if (m_swapChain)
{
- ComPtr<ID3D11Texture2D> texture;
- D3D11_TEXTURE2D_DESC textureDesc;
- m_backBufferTexture->GetDesc(&textureDesc);
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, texture.writeRef()));
-
- ComPtr<ID3D11RenderTargetView> rtv;
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- rtvDesc.Texture2D.MipSlice = 0;
- rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
- SLANG_RETURN_ON_FAIL(m_device->CreateRenderTargetView(texture, &rtvDesc, rtv.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_swapChain->GetBuffer(0, kIID_ID3D11Texture2D, (void**)m_backBufferTexture.writeRef()));
- TextureResource::Desc resourceDesc;
- resourceDesc.init2D(IResource::Type::Texture2D, Format::RGBA_Unorm_UInt8, textureDesc.Width, textureDesc.Height, 1);
-
- ComPtr<ITextureResource> primaryRenderTargetTexture;
- SLANG_RETURN_ON_FAIL(createTextureResource(IResource::Usage::RenderTarget, resourceDesc, nullptr, primaryRenderTargetTexture.writeRef()));
+ // for (int i = 0; i < 8; i++)
+ {
+ ComPtr<ID3D11Texture2D> texture;
+ D3D11_TEXTURE2D_DESC textureDesc;
+ m_backBufferTexture->GetDesc(&textureDesc);
+ SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&textureDesc, nullptr, texture.writeRef()));
- IResourceView::Desc viewDesc;
- viewDesc.format = resourceDesc.format;
- viewDesc.type = IResourceView::Type::RenderTarget;
- ComPtr<IResourceView> primaryRenderTargetView;
- SLANG_RETURN_ON_FAIL(createTextureView(primaryRenderTargetTexture, viewDesc, primaryRenderTargetView.writeRef()));
+ ComPtr<ID3D11RenderTargetView> rtv;
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ rtvDesc.Texture2D.MipSlice = 0;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ SLANG_RETURN_ON_FAIL(m_device->CreateRenderTargetView(texture, &rtvDesc, rtv.writeRef()));
+
+ TextureResource::Desc resourceDesc;
+ resourceDesc.init2D(IResource::Type::Texture2D, Format::RGBA_Unorm_UInt8, textureDesc.Width, textureDesc.Height, 1);
+
+ ComPtr<ITextureResource> primaryRenderTargetTexture;
+ SLANG_RETURN_ON_FAIL(createTextureResource(IResource::Usage::RenderTarget, resourceDesc, nullptr, primaryRenderTargetTexture.writeRef()));
+
+ IResourceView::Desc viewDesc;
+ viewDesc.format = resourceDesc.format;
+ viewDesc.type = IResourceView::Type::RenderTarget;
+ ComPtr<IResourceView> primaryRenderTargetView;
+ SLANG_RETURN_ON_FAIL(createTextureView(primaryRenderTargetTexture, viewDesc, primaryRenderTargetView.writeRef()));
+
+ m_primaryRenderTargetTexture = dynamic_cast<TextureResourceImpl*>(primaryRenderTargetTexture.get());
+ m_primaryRenderTargetView = dynamic_cast<RenderTargetViewImpl*>(primaryRenderTargetView.get());
+ }
- m_primaryRenderTargetTexture = dynamic_cast<TextureResourceImpl*>(primaryRenderTargetTexture.get());
- m_primaryRenderTargetView = dynamic_cast<RenderTargetViewImpl*>(primaryRenderTargetView.get());
+ // m_immediateContext->OMSetRenderTargets(1, m_primaryRenderTargetView->m_rtv.readRef(), nullptr);
+ m_rtvBindings[0] = m_primaryRenderTargetView->m_rtv;
+ m_targetBindingsDirty[int(PipelineType::Graphics)] = true;
+
+ // Similarly, we are going to set up a viewport once, and then never
+ // switch, since this is a simple test app.
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = (float)desc.width;
+ viewport.Height = (float)desc.height;
+ viewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
+ viewport.MinDepth = 0;
+ m_immediateContext->RSSetViewports(1, &viewport);
}
-
-// m_immediateContext->OMSetRenderTargets(1, m_primaryRenderTargetView->m_rtv.readRef(), nullptr);
- m_rtvBindings[0] = m_primaryRenderTargetView->m_rtv;
- m_targetBindingsDirty[int(PipelineType::Graphics)] = true;
-
- // Similarly, we are going to set up a viewport once, and then never
- // switch, since this is a simple test app.
- D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0;
- viewport.TopLeftY = 0;
- viewport.Width = (float)desc.width;
- viewport.Height = (float)desc.height;
- viewport.MaxDepth = 1; // TODO(tfoley): use reversed depth
- viewport.MinDepth = 0;
- m_immediateContext->RSSetViewports(1, &viewport);
-
return SLANG_OK;
}
@@ -2123,6 +2150,7 @@ Result D3D11Renderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc
case DescriptorSlotType::SampledImage:
case DescriptorSlotType::UniformTexelBuffer:
case DescriptorSlotType::InputAttachment:
+ case DescriptorSlotType::ReadOnlyStorageBuffer:
rangeInfo.type = D3D11DescriptorSlotType::ShaderResourceView;
break;
diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp
index 3db93df50..9f208f83c 100644
--- a/tools/gfx/d3d12/render-d3d12.cpp
+++ b/tools/gfx/d3d12/render-d3d12.cpp
@@ -992,6 +992,7 @@ void D3D12Renderer::beginRender()
_resetCommandList();
// Indicate that the render target needs to be writable
+ if (m_swapChain)
{
D3D12BarrierSubmitter submitter(m_commandList);
m_renderTargets[m_renderTargetIndex]->transition(D3D12_RESOURCE_STATE_RENDER_TARGET, submitter);
@@ -1008,30 +1009,31 @@ void D3D12Renderer::endRender()
const UInt64 signalValue = m_fence.nextSignal(m_commandQueue);
m_circularResourceHeap.addSync(signalValue);
}
-
- D3D12Resource& backBuffer = *m_backBuffers[m_renderTargetIndex];
- if (m_isMultiSampled)
+ if (m_swapChain)
{
- // MSAA resolve
- D3D12Resource& renderTarget = *m_renderTargets[m_renderTargetIndex];
- assert(&renderTarget != &backBuffer);
- // Barriers to wait for the render target, and the backbuffer to be in correct state
+ D3D12Resource& backBuffer = *m_backBuffers[m_renderTargetIndex];
+ if (m_isMultiSampled)
{
- D3D12BarrierSubmitter submitter(m_commandList);
- renderTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter);
- backBuffer.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter);
- }
+ // MSAA resolve
+ D3D12Resource& renderTarget = *m_renderTargets[m_renderTargetIndex];
+ assert(&renderTarget != &backBuffer);
+ // Barriers to wait for the render target, and the backbuffer to be in correct state
+ {
+ D3D12BarrierSubmitter submitter(m_commandList);
+ renderTarget.transition(D3D12_RESOURCE_STATE_RESOLVE_SOURCE, submitter);
+ backBuffer.transition(D3D12_RESOURCE_STATE_RESOLVE_DEST, submitter);
+ }
- // Do the resolve...
- m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, m_targetFormat);
- }
+ // Do the resolve...
+ m_commandList->ResolveSubresource(backBuffer, 0, renderTarget, 0, m_targetFormat);
+ }
- // Make the back buffer presentable
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- backBuffer.transition(D3D12_RESOURCE_STATE_PRESENT, submitter);
+ // Make the back buffer presentable
+ {
+ D3D12BarrierSubmitter submitter(m_commandList);
+ backBuffer.transition(D3D12_RESOURCE_STATE_PRESENT, submitter);
+ }
}
-
SLANG_ASSERT_VOID_ON_FAIL(m_commandList->Close());
{
@@ -1523,51 +1525,54 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
SLANG_RETURN_ON_FAIL(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(m_commandQueue.writeRef())));
- // Describe the swap chain.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
- swapChainDesc.BufferCount = m_numRenderTargets;
- swapChainDesc.BufferDesc.Width = m_desc.width;
- swapChainDesc.BufferDesc.Height = m_desc.height;
- swapChainDesc.BufferDesc.Format = m_targetFormat;
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
- swapChainDesc.OutputWindow = m_hwnd;
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.Windowed = TRUE;
-
- if (m_isFullSpeed)
+ if (inWindowHandle)
{
- m_hasVsync = false;
- m_allowFullScreen = false;
- }
+ // Describe the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = m_numRenderTargets;
+ swapChainDesc.BufferDesc.Width = m_desc.width;
+ swapChainDesc.BufferDesc.Height = m_desc.height;
+ swapChainDesc.BufferDesc.Format = m_targetFormat;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ swapChainDesc.OutputWindow = m_hwnd;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
- if (!m_hasVsync)
- {
- swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
- }
+ if (m_isFullSpeed)
+ {
+ m_hasVsync = false;
+ m_allowFullScreen = false;
+ }
- // Swap chain needs the queue so that it can force a flush on it.
- ComPtr<IDXGISwapChain> swapChain;
- SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
- SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
+ if (!m_hasVsync)
+ {
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+ }
- if (!m_hasVsync)
- {
- m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
+ // Swap chain needs the queue so that it can force a flush on it.
+ ComPtr<IDXGISwapChain> swapChain;
+ SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->CreateSwapChain(m_commandQueue, &swapChainDesc, swapChain.writeRef()));
+ SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
- int maxLatency = m_numRenderTargets - 2;
+ if (!m_hasVsync)
+ {
+ m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
- // Make sure the maximum latency is in the range required by dx12 runtime
- maxLatency = (maxLatency < 1) ? 1 : maxLatency;
- maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) ? DXGI_MAX_SWAP_CHAIN_BUFFERS : maxLatency;
+ int maxLatency = m_numRenderTargets - 2;
- m_swapChain->SetMaximumFrameLatency(maxLatency);
- }
+ // Make sure the maximum latency is in the range required by dx12 runtime
+ maxLatency = (maxLatency < 1) ? 1 : maxLatency;
+ maxLatency = (maxLatency > DXGI_MAX_SWAP_CHAIN_BUFFERS) ? DXGI_MAX_SWAP_CHAIN_BUFFERS : maxLatency;
+
+ m_swapChain->SetMaximumFrameLatency(maxLatency);
+ }
- // This sample does not support fullscreen transitions.
- SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
+ // This sample does not support fullscreen transitions.
+ SLANG_RETURN_ON_FAIL(m_deviceInfo.m_dxgiFactory->MakeWindowAssociation(m_hwnd, DXGI_MWA_NO_ALT_ENTER));
- m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
+ m_renderTargetIndex = m_swapChain->GetCurrentBackBufferIndex();
+ }
// Create descriptor heaps.
@@ -1583,9 +1588,7 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
SLANG_RETURN_ON_FAIL(m_samplerAllocator.init(m_device, 16, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER));
// Setup frame resources
- {
- SLANG_RETURN_ON_FAIL(createFrameResources());
- }
+ SLANG_RETURN_ON_FAIL(createFrameResources());
// Setup fence, and close the command list (as default state without begin/endRender is closed)
{
@@ -1614,7 +1617,15 @@ Result D3D12Renderer::initialize(const Desc& desc, void* inWindowHandle)
Result D3D12Renderer::createFrameResources()
{
+ // Set up frames
+ for (int i = 0; i < m_numRenderFrames; i++)
+ {
+ FrameInfo& frame = m_frameInfos[i];
+ SLANG_RETURN_ON_FAIL(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(frame.m_commandAllocator.writeRef())));
+ }
+
// Create back buffers
+ if (m_swapChain)
{
// D3D12_CPU_DESCRIPTOR_HANDLE rtvStart(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
@@ -1678,13 +1689,7 @@ Result D3D12Renderer::createFrameResources()
}
}
- // Set up frames
- for (int i = 0; i < m_numRenderFrames; i++)
- {
- FrameInfo& frame = m_frameInfos[i];
- SLANG_RETURN_ON_FAIL(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(frame.m_commandAllocator.writeRef())));
- }
-
+ if (m_swapChain)
{
D3D12_RESOURCE_DESC desc = m_backBuffers[0]->getResource()->GetDesc();
assert(desc.Width == UINT64(m_desc.width) && desc.Height == UINT64(m_desc.height));
@@ -2367,7 +2372,7 @@ Result D3D12Renderer::createBufferView(IBufferResource* buffer, IResourceView::D
srvDesc.Format = D3DUtil::getMapFormat(desc.format);
srvDesc.Buffer.StructureByteStride = 0;
srvDesc.Buffer.FirstElement = 0;
-
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if(resourceDesc.elementSize)
{
srvDesc.Buffer.StructureByteStride = resourceDesc.elementSize;
@@ -3374,7 +3379,21 @@ Result D3D12Renderer::createDescriptorSetLayout(const IDescriptorSetLayout::Desc
dxRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
}
break;
+ case DescriptorSlotType::ReadOnlyStorageBuffer:
+ {
+ if (dxRegister < 0)
+ {
+ dxRegister = srvRegisterCounter;
+ }
+ srvRegisterCounter = dxRegister + bindingCount;
+ dxRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ dxRange.NumDescriptors = UINT(bindingCount);
+ dxRange.BaseShaderRegister = UINT(dxRegister);
+ dxRange.RegisterSpace = UINT(bindingSpace);
+ dxRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+ }
+ break;
case DescriptorSlotType::UniformBuffer:
case DescriptorSlotType::DynamicUniformBuffer:
{
diff --git a/tools/gfx/render-graphics-common.cpp b/tools/gfx/render-graphics-common.cpp
index 92ccc376c..747659d11 100644
--- a/tools/gfx/render-graphics-common.cpp
+++ b/tools/gfx/render-graphics-common.cpp
@@ -146,7 +146,7 @@ public:
CASE(MutableTexture, StorageImage);
CASE(TypedBuffer, UniformTexelBuffer);
CASE(MutableTypedBuffer, StorageTexelBuffer);
- CASE(RawBuffer, UniformBuffer);
+ CASE(RawBuffer, ReadOnlyStorageBuffer);
CASE(MutableRawBuffer, StorageBuffer);
CASE(InputRenderTarget, InputAttachment);
CASE(InlineUniformData, InlineUniformBlock);
diff --git a/tools/gfx/render.h b/tools/gfx/render.h
index 8e1a5d665..eeef00a8f 100644
--- a/tools/gfx/render.h
+++ b/tools/gfx/render.h
@@ -684,6 +684,7 @@ enum class DescriptorSlotType
UniformTexelBuffer,
StorageTexelBuffer,
UniformBuffer,
+ ReadOnlyStorageBuffer,
StorageBuffer,
DynamicUniformBuffer,
DynamicStorageBuffer,
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index 4e43bf249..88cd52ad7 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -2418,6 +2418,7 @@ static VkDescriptorType translateDescriptorType(DescriptorSlotType type)
CASE(UniformTexelBuffer, UNIFORM_TEXEL_BUFFER);
CASE(StorageTexelBuffer, STORAGE_TEXEL_BUFFER);
CASE(UniformBuffer, UNIFORM_BUFFER);
+ CASE(ReadOnlyStorageBuffer, STORAGE_BUFFER);
CASE(StorageBuffer, STORAGE_BUFFER);
CASE(DynamicUniformBuffer, UNIFORM_BUFFER_DYNAMIC);
CASE(DynamicStorageBuffer, STORAGE_BUFFER_DYNAMIC);