summaryrefslogtreecommitdiffstats
path: root/tools/render-test/render-d3d11.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-06-28 11:14:48 -0700
committerGitHub <noreply@github.com>2018-06-28 11:14:48 -0700
commitdfe13b54286b27dd15f591455bbb86b7798285c2 (patch)
tree4a11f01feaae059b6c11bdfbe12a614228af6dd5 /tools/render-test/render-d3d11.cpp
parent22033f06573f900dc030c487b2c30feddf3d8f16 (diff)
Share graphics API layer between tests/examples (#603)
The `render-test` project has an in-progress graphics API abstraction layer, and it makes sense to share this code with our examples rather than write a bunch of redundant code between examples and tests. Most of this change is just moving files from `tools/render-test/*` to a new library project at `tools/slang-graphics/`. The most complicated code change there is renaming from `render_test` to `slang_graphics`. The existing `hello` example was ported to use the graphics API layer instead of raw D3D11 API calls. It is still hard-coded to use the D3D11 back-end and the `SLANG_DXBC` target, so more work is needed if we want to actually support multiple APIs in the examples. I also went ahead and implemented an extremely rudimentary set of APIs to abstract over the Windows platform calls that were being made in the example, so that we could potentially run that same example on other platforms. I did *not* port `render-test` to use those APIs, and I also did not implement them for anything but Windows (my assumption is that for most other platforms we would just use SDL2, and require people to ensure it is installed to their machine before building Slang examples).
Diffstat (limited to 'tools/render-test/render-d3d11.cpp')
-rw-r--r--tools/render-test/render-d3d11.cpp1101
1 files changed, 0 insertions, 1101 deletions
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
deleted file mode 100644
index 109c5aca1..000000000
--- a/tools/render-test/render-d3d11.cpp
+++ /dev/null
@@ -1,1101 +0,0 @@
-// render-d3d11.cpp
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include "render-d3d11.h"
-
-#include "options.h"
-#include "render.h"
-#include "d3d-util.h"
-
-#include "surface.h"
-
-// In order to use the Slang API, we need to include its header
-
-#include <slang.h>
-
-#include "../../slang-com-ptr.h"
-
-// We will be rendering with Direct3D 11, so we need to include
-// the Windows and D3D11 headers
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <Windows.h>
-#undef WIN32_LEAN_AND_MEAN
-#undef NOMINMAX
-
-#include <d3d11_2.h>
-#include <d3dcompiler.h>
-
-// We will use the C standard library just for printing error messages.
-#include <stdio.h>
-
-#ifdef _MSC_VER
-#include <stddef.h>
-#if (_MSC_VER < 1900)
-#define snprintf sprintf_s
-#endif
-#endif
-//
-using namespace Slang;
-
-namespace renderer_test {
-
-class D3D11Renderer : public Renderer
-{
-public:
- // Renderer implementation
- virtual SlangResult initialize(const Desc& desc, void* inWindowHandle) override;
- virtual void setClearColor(const float color[4]) override;
- virtual void clearFrame() override;
- virtual void presentFrame() override;
- virtual TextureResource* createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
- virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
- virtual SlangResult captureScreenSurface(Surface& surfaceOut) override;
- virtual InputLayout* createInputLayout( const InputElementDesc* inputElements, UInt inputElementCount) override;
- virtual BindingState* createBindingState(const BindingState::Desc& desc) override;
- virtual ShaderProgram* createProgram(const ShaderProgram::Desc& desc) override;
- virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
- virtual void unmap(BufferResource* buffer) override;
- virtual void setInputLayout(InputLayout* inputLayout) override;
- virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
- virtual void setBindingState(BindingState * state);
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
- virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void draw(UInt vertexCount, UInt startVertex) override;
- virtual void dispatchCompute(int x, int y, int z) override;
- virtual void submitGpuWork() override {}
- virtual void waitForGpu() override {}
- virtual RendererType getRendererType() const override { return RendererType::DirectX11; }
-
- protected:
-
- struct BindingDetail
- {
- ComPtr<ID3D11ShaderResourceView> m_srv;
- ComPtr<ID3D11UnorderedAccessView> m_uav;
- ComPtr<ID3D11SamplerState> m_samplerState;
- };
-
- class BindingStateImpl: public BindingState
- {
- public:
- typedef BindingState Parent;
-
- /// Ctor
- BindingStateImpl(const Desc& desc):
- Parent(desc)
- {}
-
- List<BindingDetail> m_bindingDetails;
- };
-
- class ShaderProgramImpl: public ShaderProgram
- {
- public:
- ComPtr<ID3D11VertexShader> m_vertexShader;
- ComPtr<ID3D11PixelShader> m_pixelShader;
- ComPtr<ID3D11ComputeShader> m_computeShader;
- };
-
- class BufferResourceImpl: public BufferResource
- {
- public:
- typedef BufferResource Parent;
-
- BufferResourceImpl(const Desc& desc, Usage initialUsage):
- Parent(desc),
- m_initialUsage(initialUsage)
- {
- }
-
- MapFlavor m_mapFlavor;
- Usage m_initialUsage;
- ComPtr<ID3D11Buffer> m_buffer;
- ComPtr<ID3D11Buffer> m_staging;
- };
- class TextureResourceImpl : public TextureResource
- {
- public:
- typedef TextureResource Parent;
-
- TextureResourceImpl(const Desc& desc, Usage initialUsage) :
- Parent(desc),
- m_initialUsage(initialUsage)
- {
- }
- Usage m_initialUsage;
- ComPtr<ID3D11Resource> m_resource;
- };
-
- class InputLayoutImpl: public InputLayout
- {
- public:
- ComPtr<ID3D11InputLayout> m_layout;
- };
-
- /// Capture a texture to a file
- static HRESULT captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut);
-
- void _applyBindingState(bool isCompute);
-
- ComPtr<IDXGISwapChain> m_swapChain;
- ComPtr<ID3D11Device> m_device;
- ComPtr<ID3D11DeviceContext> m_immediateContext;
- ComPtr<ID3D11Texture2D> m_backBufferTexture;
-
- List<ComPtr<ID3D11RenderTargetView> > m_renderTargetViews;
- List<ComPtr<ID3D11Texture2D> > m_renderTargetTextures;
-
- RefPtr<BindingStateImpl> m_currentBindings;
-
- Desc m_desc;
-
- float m_clearColor[4] = { 0, 0, 0, 0 };
-};
-
-Renderer* createD3D11Renderer()
-{
- return new D3D11Renderer();
-}
-
-/* static */HRESULT D3D11Renderer::captureTextureToSurface(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, Surface& surfaceOut)
-{
- if (!context) return E_INVALIDARG;
- if (!texture) return E_INVALIDARG;
-
- D3D11_TEXTURE2D_DESC textureDesc;
- texture->GetDesc(&textureDesc);
-
- // Don't bother supporting MSAA for right now
- if (textureDesc.SampleDesc.Count > 1)
- {
- fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
- return E_INVALIDARG;
- }
-
- HRESULT hr = S_OK;
- ComPtr<ID3D11Texture2D> stagingTexture;
-
- if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
- {
- stagingTexture = texture;
- }
- else
- {
- // Modify the descriptor to give us a staging texture
- textureDesc.BindFlags = 0;
- textureDesc.MiscFlags &= ~D3D11_RESOURCE_MISC_TEXTURECUBE;
- textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- textureDesc.Usage = D3D11_USAGE_STAGING;
-
- hr = device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
- if (FAILED(hr))
- {
- fprintf(stderr, "ERROR: failed to create staging texture\n");
- return hr;
- }
-
- context->CopyResource(stagingTexture, texture);
- }
-
- // Now just read back texels from the staging textures
- {
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- SLANG_RETURN_ON_FAIL(context->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
-
- Result res = surfaceOut.set(textureDesc.Width, textureDesc.Height, Format::RGBA_Unorm_UInt8, mappedResource.RowPitch, mappedResource.pData, SurfaceAllocator::getMallocAllocator());
-
- // Make sure to unmap
- context->Unmap(stagingTexture, 0);
- return res;
- }
-}
-
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
-
-SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
-{
- auto windowHandle = (HWND)inWindowHandle;
- m_desc = desc;
-
- // Rather than statically link against D3D, we load it dynamically.
- HMODULE d3dModule = LoadLibraryA("d3d11.dll");
- if (!d3dModule)
- {
- fprintf(stderr, "error: failed load 'd3d11.dll'\n");
- return SLANG_FAIL;
- }
-
- PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN D3D11CreateDeviceAndSwapChain_ =
- (PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN)GetProcAddress(d3dModule, "D3D11CreateDeviceAndSwapChain");
- if (!D3D11CreateDeviceAndSwapChain_)
- {
- fprintf(stderr,
- "error: failed load symbol 'D3D11CreateDeviceAndSwapChain'\n");
- return SLANG_FAIL;
- }
-
- // We create our device in debug mode, just so that we can check that the
- // example doesn't trigger warnings.
- UINT deviceFlags = 0;
- deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
-
- // Our swap chain uses RGBA8 with sRGB, with double buffering.
- DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
- swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
-
- // Note(tfoley): Disabling sRGB for DX back buffer for now, so that we
- // can get consistent output with OpenGL, where setting up sRGB will
- // probably be more involved.
- // swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
- swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
-
- swapChainDesc.SampleDesc.Count = 1;
- swapChainDesc.SampleDesc.Quality = 0;
- swapChainDesc.BufferCount = 2;
- swapChainDesc.OutputWindow = windowHandle;
- swapChainDesc.Windowed = TRUE;
- swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
- swapChainDesc.Flags = 0;
-
- // We will ask for the highest feature level that can be supported.
- const D3D_FEATURE_LEVEL featureLevels[] = {
- D3D_FEATURE_LEVEL_11_1,
- D3D_FEATURE_LEVEL_11_0,
- D3D_FEATURE_LEVEL_10_1,
- D3D_FEATURE_LEVEL_10_0,
- D3D_FEATURE_LEVEL_9_3,
- D3D_FEATURE_LEVEL_9_2,
- D3D_FEATURE_LEVEL_9_1,
- };
- D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1;
- const int totalNumFeatureLevels = SLANG_COUNT_OF(featureLevels);
-
- // On a machine that does not have an up-to-date version of D3D installed,
- // the `D3D11CreateDeviceAndSwapChain` call will fail with `E_INVALIDARG`
- // if you ask for featuer level 11_1. The workaround is to call
- // `D3D11CreateDeviceAndSwapChain` up to twice: the first time with 11_1
- // at the start of the list of requested feature levels, and the second
- // time without it.
-
- for (int ii = 0; ii < 2; ++ii)
- {
- const HRESULT hr = D3D11CreateDeviceAndSwapChain_(
- nullptr, // adapter (use default)
- D3D_DRIVER_TYPE_REFERENCE,
- //D3D_DRIVER_TYPE_HARDWARE,
- nullptr, // software
- deviceFlags,
- &featureLevels[ii],
- totalNumFeatureLevels - ii,
- D3D11_SDK_VERSION,
- &swapChainDesc,
- m_swapChain.writeRef(),
- m_device.writeRef(),
- &featureLevel,
- m_immediateContext.writeRef());
-
- // Failures with `E_INVALIDARG` might be due to feature level 11_1
- // not being supported.
- if (hr == E_INVALIDARG)
- {
- continue;
- }
-
- // Other failures are real, though.
- SLANG_RETURN_ON_FAIL(hr);
- // We must have a swap chain
- break;
- }
-
- // After we've created the swap chain, we can request a pointer to the
- // back buffer as a D3D11 texture, and create a render-target view from it.
-
- 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++)
- {
- 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()));
-
- m_renderTargetViews.Add(rtv);
- m_renderTargetTextures.Add(texture);
- }
-
- m_immediateContext->OMSetRenderTargets((UINT)m_renderTargetViews.Count(), m_renderTargetViews.Buffer()->readRef(), nullptr);
-
- // 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;
-}
-
-void D3D11Renderer::setClearColor(const float color[4])
-{
- memcpy(m_clearColor, color, sizeof(m_clearColor));
-}
-
-void D3D11Renderer::clearFrame()
-{
- for (auto i = 0u; i < m_renderTargetViews.Count(); i++)
- {
- m_immediateContext->ClearRenderTargetView(m_renderTargetViews[i], m_clearColor);
- }
-}
-
-void D3D11Renderer::presentFrame()
-{
- m_immediateContext->CopyResource(m_backBufferTexture, m_renderTargetTextures[0]);
- m_swapChain->Present(0, 0);
-}
-
-SlangResult D3D11Renderer::captureScreenSurface(Surface& surfaceOut)
-{
- return captureTextureToSurface(m_device, m_immediateContext, m_renderTargetTextures[0], surfaceOut);
-}
-
-static D3D11_BIND_FLAG _calcResourceFlag(Resource::BindFlag::Enum bindFlag)
-{
- typedef Resource::BindFlag BindFlag;
- switch (bindFlag)
- {
- case BindFlag::VertexBuffer: return D3D11_BIND_VERTEX_BUFFER;
- case BindFlag::IndexBuffer: return D3D11_BIND_INDEX_BUFFER;
- case BindFlag::ConstantBuffer: return D3D11_BIND_CONSTANT_BUFFER;
- case BindFlag::StreamOutput: return D3D11_BIND_STREAM_OUTPUT;
- case BindFlag::RenderTarget: return D3D11_BIND_RENDER_TARGET;
- case BindFlag::DepthStencil: return D3D11_BIND_DEPTH_STENCIL;
- case BindFlag::UnorderedAccess: return D3D11_BIND_UNORDERED_ACCESS;
- case BindFlag::PixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
- case BindFlag::NonPixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
- default: return D3D11_BIND_FLAG(0);
- }
-}
-
-static int _calcResourceBindFlags(int bindFlags)
-{
- int dstFlags = 0;
- while (bindFlags)
- {
- int lsb = bindFlags & -bindFlags;
-
- dstFlags |= _calcResourceFlag(Resource::BindFlag::Enum(lsb));
- bindFlags &= ~lsb;
- }
- return dstFlags;
-}
-
-static int _calcResourceAccessFlags(int accessFlags)
-{
- switch (accessFlags)
- {
- case 0: return 0;
- case Resource::AccessFlag::Read: return D3D11_CPU_ACCESS_READ;
- case Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_WRITE;
- case Resource::AccessFlag::Read |
- Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
- default: assert(!"Invalid flags"); return 0;
- }
-}
-
-TextureResource* D3D11Renderer::createTextureResource(Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
-{
- TextureResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- const int effectiveArraySize = srcDesc.calcEffectiveArraySize();
-
- assert(initData);
- assert(initData->numSubResources == srcDesc.numMipLevels * effectiveArraySize * srcDesc.size.depth);
-
- const DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc.format);
- if (format == DXGI_FORMAT_UNKNOWN)
- {
- return nullptr;
- }
-
- const int bindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
-
- // Set up the initialize data
- List<D3D11_SUBRESOURCE_DATA> subRes;
- subRes.SetSize(srcDesc.numMipLevels * effectiveArraySize);
- {
- int subResourceIndex = 0;
- for (int i = 0; i < effectiveArraySize; i++)
- {
- for (int j = 0; j < srcDesc.numMipLevels; j++)
- {
- const int mipHeight = TextureResource::calcMipSize(srcDesc.size.height, j);
-
- D3D11_SUBRESOURCE_DATA& data = subRes[subResourceIndex];
-
- data.pSysMem = initData->subResources[subResourceIndex];
-
- data.SysMemPitch = UINT(initData->mipRowStrides[j]);
- data.SysMemSlicePitch = UINT(initData->mipRowStrides[j] * mipHeight);
-
- subResourceIndex++;
- }
- }
- }
-
- const int accessFlags = _calcResourceAccessFlags(srcDesc.cpuAccessFlags);
-
- RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(srcDesc, initialUsage));
-
- switch (srcDesc.type)
- {
- case Resource::Type::Texture1D:
- {
- D3D11_TEXTURE1D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.ArraySize = effectiveArraySize;
- desc.Width = srcDesc.size.width;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ComPtr<ID3D11Texture1D> texture1D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture1D(&desc, subRes.Buffer(), texture1D.writeRef()));
-
- texture->m_resource = texture1D;
- break;
- }
- case Resource::Type::TextureCube:
- case Resource::Type::Texture2D:
- {
- D3D11_TEXTURE2D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.ArraySize = effectiveArraySize;
-
- desc.Width = srcDesc.size.width;
- desc.Height = srcDesc.size.height;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.SampleDesc.Count = srcDesc.sampleDesc.numSamples;
- desc.SampleDesc.Quality = srcDesc.sampleDesc.quality;
-
- if (srcDesc.type == Resource::Type::TextureCube)
- {
- desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
- }
-
- ComPtr<ID3D11Texture2D> texture2D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture2D(&desc, subRes.Buffer(), texture2D.writeRef()));
-
- texture->m_resource = texture2D;
- break;
- }
- case Resource::Type::Texture3D:
- {
- D3D11_TEXTURE3D_DESC desc = { 0 };
- desc.BindFlags = bindFlags;
- desc.CPUAccessFlags = accessFlags;
- desc.Format = format;
- desc.MiscFlags = 0;
- desc.MipLevels = srcDesc.numMipLevels;
- desc.Width = srcDesc.size.width;
- desc.Height = srcDesc.size.height;
- desc.Depth = srcDesc.size.depth;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ComPtr<ID3D11Texture3D> texture3D;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture3D(&desc, subRes.Buffer(), texture3D.writeRef()));
-
- texture->m_resource = texture3D;
- break;
- }
- default: return nullptr;
- }
-
- return texture.detach();
-}
-
-BufferResource* D3D11Renderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
-{
- BufferResource::Desc srcDesc(descIn);
- srcDesc.setDefaults(initialUsage);
-
- // Make aligned to 256 bytes... not sure why, but if you remove this the tests do fail.
- const size_t alignedSizeInBytes = D3DUtil::calcAligned(srcDesc.sizeInBytes, 256);
-
- // Hack to make the initialization never read from out of bounds memory, by copying into a buffer
- List<uint8_t> initDataBuffer;
- if (initData && alignedSizeInBytes > srcDesc.sizeInBytes)
- {
- initDataBuffer.SetSize(alignedSizeInBytes);
- ::memcpy(initDataBuffer.Buffer(), initData, srcDesc.sizeInBytes);
- initData = initDataBuffer.Buffer();
- }
-
- D3D11_BUFFER_DESC bufferDesc = { 0 };
- bufferDesc.ByteWidth = UINT(alignedSizeInBytes);
- bufferDesc.BindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
- // For read we'll need to do some staging
- bufferDesc.CPUAccessFlags = _calcResourceAccessFlags(descIn.cpuAccessFlags & Resource::AccessFlag::Write);
- bufferDesc.Usage = D3D11_USAGE_DEFAULT;
-
- // If written by CPU, make it dynamic
- if (descIn.cpuAccessFlags & Resource::AccessFlag::Write)
- {
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- }
-
- switch (initialUsage)
- {
- case Resource::Usage::ConstantBuffer:
- {
- // We'll just assume ConstantBuffers are dynamic for now
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- break;
- }
- default: break;
- }
-
- if (bufferDesc.BindFlags & (D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE))
- {
- //desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
- if (srcDesc.elementSize != 0)
- {
- bufferDesc.StructureByteStride = srcDesc.elementSize;
- bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
- }
- else
- {
- bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- }
- }
-
- D3D11_SUBRESOURCE_DATA subResourceData = { 0 };
- subResourceData.pSysMem = initData;
-
- RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(srcDesc, initialUsage));
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufferDesc, initData ? &subResourceData : nullptr, buffer->m_buffer.writeRef()));
-
- if (srcDesc.cpuAccessFlags & Resource::AccessFlag::Read)
- {
- D3D11_BUFFER_DESC bufDesc = {};
- bufDesc.BindFlags = 0;
- bufDesc.ByteWidth = (UINT)alignedSizeInBytes;
- bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- bufDesc.Usage = D3D11_USAGE_STAGING;
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufDesc, nullptr, buffer->m_staging.writeRef()));
- }
-
- return buffer.detach();
-}
-
-InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputElementsIn, UInt inputElementCount)
-{
- D3D11_INPUT_ELEMENT_DESC inputElements[16] = {};
-
- char hlslBuffer[1024];
- char* hlslCursor = &hlslBuffer[0];
-
- hlslCursor += sprintf(hlslCursor, "float4 main(\n");
-
- for (UInt ii = 0; ii < inputElementCount; ++ii)
- {
- inputElements[ii].SemanticName = inputElementsIn[ii].semanticName;
- inputElements[ii].SemanticIndex = (UINT)inputElementsIn[ii].semanticIndex;
- inputElements[ii].Format = D3DUtil::getMapFormat(inputElementsIn[ii].format);
- inputElements[ii].InputSlot = 0;
- inputElements[ii].AlignedByteOffset = (UINT)inputElementsIn[ii].offset;
- inputElements[ii].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
- inputElements[ii].InstanceDataStepRate = 0;
-
- if (ii != 0)
- {
- hlslCursor += sprintf(hlslCursor, ",\n");
- }
-
- char const* typeName = "Unknown";
- switch (inputElementsIn[ii].format)
- {
- case Format::RGBA_Float32:
- typeName = "float4";
- break;
- case Format::RGB_Float32:
- typeName = "float3";
- break;
- case Format::RG_Float32:
- typeName = "float2";
- break;
- case Format::R_Float32:
- typeName = "float";
- break;
- default:
- return nullptr;
- }
-
- hlslCursor += sprintf(hlslCursor, "%s a%d : %s%d",
- typeName,
- (int)ii,
- inputElementsIn[ii].semanticName,
- (int)inputElementsIn[ii].semanticIndex);
- }
-
- hlslCursor += sprintf(hlslCursor, "\n) : SV_Position { return 0; }");
-
- ComPtr<ID3DBlob> vertexShaderBlob;
- SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader("inputLayout", hlslBuffer, "main", "vs_5_0", vertexShaderBlob));
-
- ComPtr<ID3D11InputLayout> inputLayout;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateInputLayout(&inputElements[0], (UINT)inputElementCount, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(),
- inputLayout.writeRef()));
-
- InputLayoutImpl* impl = new InputLayoutImpl;
- impl->m_layout.swap(inputLayout);
-
- return impl;
-}
-
-void* D3D11Renderer::map(BufferResource* bufferIn, MapFlavor flavor)
-{
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
-
- D3D11_MAP mapType;
- ID3D11Buffer* buffer = bufferResource->m_buffer;
-
- switch (flavor)
- {
- case MapFlavor::WriteDiscard:
- mapType = D3D11_MAP_WRITE_DISCARD;
- break;
- case MapFlavor::HostWrite:
- mapType = D3D11_MAP_WRITE;
- break;
- case MapFlavor::HostRead:
- mapType = D3D11_MAP_READ;
-
- buffer = bufferResource->m_staging;
- if (!buffer)
- {
- return nullptr;
- }
-
- // Okay copy the data over
- m_immediateContext->CopyResource(buffer, bufferResource->m_buffer);
-
- break;
- default:
- return nullptr;
- }
-
- // We update our constant buffer per-frame, just for the purposes
- // of the example, but we don't actually load different data
- // per-frame (we always use an identity projection).
- D3D11_MAPPED_SUBRESOURCE mappedSub;
- SLANG_RETURN_NULL_ON_FAIL(m_immediateContext->Map(buffer, 0, mapType, 0, &mappedSub));
-
- bufferResource->m_mapFlavor = flavor;
-
- return mappedSub.pData;
-}
-
-void D3D11Renderer::unmap(BufferResource* bufferIn)
-{
- BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
- ID3D11Buffer* buffer = (bufferResource->m_mapFlavor == MapFlavor::HostRead) ? bufferResource->m_staging : bufferResource->m_buffer;
- m_immediateContext->Unmap(buffer, 0);
-}
-
-void D3D11Renderer::setInputLayout(InputLayout* inputLayoutIn)
-{
- auto inputLayout = static_cast<InputLayoutImpl*>(inputLayoutIn);
- m_immediateContext->IASetInputLayout(inputLayout->m_layout);
-}
-
-void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
-{
- m_immediateContext->IASetPrimitiveTopology(D3DUtil::getPrimitiveTopology(topology));
-}
-
-void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffersIn, const UInt* stridesIn, const UInt* offsetsIn)
-{
- static const int kMaxVertexBuffers = 16;
- assert(slotCount <= kMaxVertexBuffers);
-
- UINT vertexStrides[kMaxVertexBuffers];
- UINT vertexOffsets[kMaxVertexBuffers];
- ID3D11Buffer* dxBuffers[kMaxVertexBuffers];
-
- auto buffers = (BufferResourceImpl*const*)buffersIn;
-
- for (UInt ii = 0; ii < slotCount; ++ii)
- {
- vertexStrides[ii] = (UINT)stridesIn[ii];
- vertexOffsets[ii] = (UINT)offsetsIn[ii];
- dxBuffers[ii] = buffers[ii]->m_buffer;
- }
-
- m_immediateContext->IASetVertexBuffers((UINT)startSlot, (UINT)slotCount, dxBuffers, &vertexStrides[0], &vertexOffsets[0]);
-}
-
-void D3D11Renderer::setShaderProgram(ShaderProgram* programIn)
-{
- auto program = (ShaderProgramImpl*)programIn;
- m_immediateContext->CSSetShader(program->m_computeShader, nullptr, 0);
- m_immediateContext->VSSetShader(program->m_vertexShader, nullptr, 0);
- m_immediateContext->PSSetShader(program->m_pixelShader, nullptr, 0);
-}
-
-void D3D11Renderer::draw(UInt vertexCount, UInt startVertex)
-{
- _applyBindingState(false);
- m_immediateContext->Draw((UINT)vertexCount, (UINT)startVertex);
-}
-
-ShaderProgram* D3D11Renderer::createProgram(const ShaderProgram::Desc& desc)
-{
- if (desc.pipelineType == PipelineType::Compute)
- {
- auto computeKernel = desc.findKernel(StageType::Compute);
-
- ComPtr<ID3D11ComputeShader> computeShader;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateComputeShader(computeKernel->codeBegin, computeKernel->getCodeSize(), nullptr, computeShader.writeRef()));
-
- ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->m_computeShader.swap(computeShader);
- return shaderProgram;
- }
- else
- {
- auto vertexKernel = desc.findKernel(StageType::Vertex);
- auto fragmentKernel = desc.findKernel(StageType::Fragment);
-
- ComPtr<ID3D11VertexShader> vertexShader;
- ComPtr<ID3D11PixelShader> pixelShader;
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateVertexShader(vertexKernel->codeBegin, vertexKernel->getCodeSize(), nullptr, vertexShader.writeRef()));
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreatePixelShader(fragmentKernel->codeBegin, fragmentKernel->getCodeSize(), nullptr, pixelShader.writeRef()));
-
- ShaderProgramImpl* shaderProgram = new ShaderProgramImpl();
- shaderProgram->m_vertexShader.swap(vertexShader);
- shaderProgram->m_pixelShader.swap(pixelShader);
- return shaderProgram;
- }
-}
-
-void D3D11Renderer::dispatchCompute(int x, int y, int z)
-{
- _applyBindingState(true);
- m_immediateContext->Dispatch(x, y, z);
-}
-
-BindingState* D3D11Renderer::createBindingState(const BindingState::Desc& bindingStateDesc)
-{
- RefPtr<BindingStateImpl> bindingState(new BindingStateImpl(bindingStateDesc));
-
- const auto& srcBindings = bindingStateDesc.m_bindings;
- const int numBindings = int(srcBindings.Count());
-
- auto& dstDetails = bindingState->m_bindingDetails;
- dstDetails.SetSize(numBindings);
-
- for (int i = 0; i < numBindings; ++i)
- {
- auto& dstDetail = dstDetails[i];
- const auto& srcBinding = srcBindings[i];
-
- assert(srcBinding.registerRange.isSingle());
-
- switch (srcBinding.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(srcBinding.resource && srcBinding.resource->isBuffer());
-
- BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(srcBinding.resource.Ptr());
- const BufferResource::Desc& bufferDesc = buffer->getDesc();
-
- const int elemSize = bufferDesc.elementSize <= 0 ? 1 : bufferDesc.elementSize;
-
- if (bufferDesc.bindFlags & Resource::BindFlag::UnorderedAccess)
- {
- D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
- memset(&viewDesc, 0, sizeof(viewDesc));
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.NumElements = (UINT)(bufferDesc.sizeInBytes / elemSize);
- viewDesc.Buffer.Flags = 0;
- viewDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- viewDesc.Format = D3DUtil::getMapFormat(bufferDesc.format);
-
- if (bufferDesc.elementSize == 0 && bufferDesc.format == Format::Unknown)
- {
- viewDesc.Buffer.Flags |= D3D11_BUFFER_UAV_FLAG_RAW;
- viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateUnorderedAccessView(buffer->m_buffer, &viewDesc, dstDetail.m_uav.writeRef()));
- }
- if (bufferDesc.bindFlags & (Resource::BindFlag::NonPixelShaderResource | Resource::BindFlag::PixelShaderResource))
- {
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- memset(&viewDesc, 0, sizeof(viewDesc));
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.ElementWidth = elemSize;
- viewDesc.Buffer.NumElements = (UINT)(bufferDesc.sizeInBytes / elemSize);
- viewDesc.Buffer.ElementOffset = 0;
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
- viewDesc.Format = DXGI_FORMAT_UNKNOWN;
-
- if (bufferDesc.elementSize == 0)
- {
- viewDesc.Format = DXGI_FORMAT_R32_FLOAT;
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateShaderResourceView(buffer->m_buffer, &viewDesc, dstDetail.m_srv.writeRef()));
- }
- break;
- }
- case BindingType::Texture:
- case BindingType::CombinedTextureSampler:
- {
- assert(srcBinding.resource && srcBinding.resource->isTexture());
-
- TextureResourceImpl* texture = static_cast<TextureResourceImpl*>(srcBinding.resource.Ptr());
-
- const TextureResource::Desc& textureDesc = texture->getDesc();
-
- D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- viewDesc.Format = D3DUtil::getMapFormat(textureDesc.format);
-
- switch (texture->getType())
- {
- case Resource::Type::Texture1D:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
- viewDesc.Texture1D.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture1D.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
- viewDesc.Texture1DArray.ArraySize = textureDesc.arraySize;
- viewDesc.Texture1DArray.FirstArraySlice = 0;
- viewDesc.Texture1DArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture1DArray.MostDetailedMip = 0;
- }
- break;
- }
- case Resource::Type::Texture2D:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- viewDesc.Texture2D.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture2D.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
- viewDesc.Texture2DArray.ArraySize = textureDesc.arraySize;
- viewDesc.Texture2DArray.FirstArraySlice = 0;
- viewDesc.Texture2DArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.Texture2DArray.MostDetailedMip = 0;
- }
- break;
- }
- case Resource::Type::TextureCube:
- {
- if (textureDesc.arraySize <= 0)
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- viewDesc.TextureCube.MipLevels = textureDesc.numMipLevels;
- viewDesc.TextureCube.MostDetailedMip = 0;
- }
- else
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
- viewDesc.TextureCubeArray.MipLevels = textureDesc.numMipLevels;
- viewDesc.TextureCubeArray.MostDetailedMip = 0;
- viewDesc.TextureCubeArray.First2DArrayFace = 0;
- viewDesc.TextureCubeArray.NumCubes = textureDesc.arraySize;
- }
- break;
- }
- case Resource::Type::Texture3D:
- {
- viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
- viewDesc.Texture3D.MipLevels = textureDesc.numMipLevels; // Old code fixed as one
- viewDesc.Texture3D.MostDetailedMip = 0;
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return nullptr;
- }
- }
-
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateShaderResourceView(texture->m_resource, &viewDesc, dstDetail.m_srv.writeRef()));
- break;
- }
- case BindingType::Sampler:
- {
- const BindingState::SamplerDesc& samplerDesc = bindingStateDesc.m_samplerDescs[srcBinding.descIndex];
-
- D3D11_SAMPLER_DESC desc = {};
- desc.AddressU = desc.AddressV = desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
-
- if (samplerDesc.isCompareSampler)
- {
- desc.ComparisonFunc = D3D11_COMPARISON_LESS_EQUAL;
- desc.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
- desc.MinLOD = desc.MaxLOD = 0.0f;
- }
- else
- {
- desc.Filter = D3D11_FILTER_ANISOTROPIC;
- desc.MaxAnisotropy = 8;
- desc.MinLOD = 0.0f;
- desc.MaxLOD = 100.0f;
- }
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateSamplerState(&desc, dstDetail.m_samplerState.writeRef()));
- break;
- }
- default:
- {
- assert(!"Unhandled type");
- return nullptr;
- }
- }
- }
-
- // Done
- return bindingState.detach();
-}
-
-void D3D11Renderer::_applyBindingState(bool isCompute)
-{
- auto context = m_immediateContext.get();
-
- const auto& details = m_currentBindings->m_bindingDetails;
- const auto& bindings = m_currentBindings->getDesc().m_bindings;
-
- const int numBindings = int(bindings.Count());
-
- for (int i = 0; i < numBindings; ++i)
- {
- const auto& binding = bindings[i];
- const auto& detail = details[i];
-
- const int bindingIndex = binding.registerRange.getSingleIndex();
-
- switch (binding.bindingType)
- {
- case BindingType::Buffer:
- {
- assert(binding.resource && binding.resource->isBuffer());
- if (binding.resource->canBind(Resource::BindFlag::ConstantBuffer))
- {
- ID3D11Buffer* buffer = static_cast<BufferResourceImpl*>(binding.resource.Ptr())->m_buffer;
- if (isCompute)
- context->CSSetConstantBuffers(bindingIndex, 1, &buffer);
- else
- {
- context->VSSetConstantBuffers(bindingIndex, 1, &buffer);
- context->PSSetConstantBuffers(bindingIndex, 1, &buffer);
- }
- }
- else if (detail.m_uav)
- {
- if (isCompute)
- context->CSSetUnorderedAccessViews(bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- else
- context->OMSetRenderTargetsAndUnorderedAccessViews(m_currentBindings->getDesc().m_numRenderTargets,
- m_renderTargetViews.Buffer()->readRef(), nullptr, bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- }
- else
- {
- if (isCompute)
- context->CSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- else
- {
- context->PSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- context->VSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- }
- }
- break;
- }
- case BindingType::Texture:
- {
- if (detail.m_uav)
- {
- if (isCompute)
- context->CSSetUnorderedAccessViews(bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- else
- context->OMSetRenderTargetsAndUnorderedAccessViews(D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL,
- nullptr, nullptr, bindingIndex, 1, detail.m_uav.readRef(), nullptr);
- }
- else
- {
- if (isCompute)
- context->CSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- else
- {
- context->PSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- context->VSSetShaderResources(bindingIndex, 1, detail.m_srv.readRef());
- }
- }
- break;
- }
- case BindingType::Sampler:
- {
- if (isCompute)
- context->CSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- else
- {
- context->PSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- context->VSSetSamplers(bindingIndex, 1, detail.m_samplerState.readRef());
- }
- break;
- }
- default:
- {
- assert(!"Not implemented");
- return;
- }
- }
- }
-}
-
-void D3D11Renderer::setBindingState(BindingState* state)
-{
- m_currentBindings = static_cast<BindingStateImpl*>(state);
-}
-
-} // renderer_test