summaryrefslogtreecommitdiffstats
path: root/tools/gfx/d3d11/render-d3d11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/d3d11/render-d3d11.cpp')
-rw-r--r--tools/gfx/d3d11/render-d3d11.cpp623
1 files changed, 355 insertions, 268 deletions
diff --git a/tools/gfx/d3d11/render-d3d11.cpp b/tools/gfx/d3d11/render-d3d11.cpp
index 49fe101fb..c64b1c3bd 100644
--- a/tools/gfx/d3d11/render-d3d11.cpp
+++ b/tools/gfx/d3d11/render-d3d11.cpp
@@ -1,9 +1,9 @@
// render-d3d11.cpp
-
#define _CRT_SECURE_NO_WARNINGS
#include "render-d3d11.h"
#include "core/slang-basic.h"
+#include "core/slang-blob.h"
//WORKING: #include "options.h"
#include "../renderer-shared.h"
@@ -63,11 +63,23 @@ public:
~D3D11Renderer() {}
// Renderer implementation
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc, void* inWindowHandle) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
virtual SLANG_NO_THROW void SLANG_MCALL setClearColor(const float color[4]) override;
virtual SLANG_NO_THROW void SLANG_MCALL clearFrame() override;
- virtual SLANG_NO_THROW void SLANG_MCALL presentFrame() override;
- virtual SLANG_NO_THROW TextureResource::Desc SLANG_MCALL getSwapChainTextureDesc() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL beginFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL endFrame() override;
+ virtual SLANG_NO_THROW void SLANG_MCALL
+ makeSwapchainImagePresentable(ISwapchain* swapchain) override
+ {
+ SLANG_UNUSED(swapchain);
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createFramebuffer(const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer) override;
+ virtual SLANG_NO_THROW void SLANG_MCALL setFramebuffer(IFramebuffer* frameBuffer) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource(
IResource::Usage initialUsage,
@@ -96,8 +108,10 @@ public:
const IDescriptorSetLayout::Desc& desc, IDescriptorSetLayout** outLayout) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createPipelineLayout(const IPipelineLayout::Desc& desc, IPipelineLayout** outLayout) override;
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createDescriptorSet(
+ IDescriptorSetLayout* layout,
+ IDescriptorSet::Flag::Enum flag,
+ IDescriptorSet** outDescriptorSet) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createProgram(const IShaderProgram::Desc& desc, IShaderProgram** outProgram) override;
@@ -106,8 +120,8 @@ public:
virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState(
const ComputePipelineStateDesc& desc, IPipelineState** outState) override;
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize) override;
+ virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource(
+ ITextureResource* texture, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize) override;
virtual SLANG_NO_THROW void* SLANG_MCALL map(IBufferResource* buffer, MapFlavor flavor) override;
virtual SLANG_NO_THROW void SLANG_MCALL unmap(IBufferResource* buffer) override;
@@ -129,8 +143,6 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL
setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override;
virtual SLANG_NO_THROW void SLANG_MCALL
- setDepthStencilTarget(IResourceView* depthStencilView) override;
- virtual SLANG_NO_THROW void SLANG_MCALL
setViewports(UInt count, Viewport const* viewports) override;
virtual SLANG_NO_THROW void SLANG_MCALL
setScissorRects(UInt count, ScissorRect const* rects) override;
@@ -432,6 +444,175 @@ public:
ComPtr<ID3D11RenderTargetView> m_rtv;
};
+ class FramebufferLayoutImpl
+ : public IFramebufferLayout
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebufferLayout* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebufferLayout)
+ return static_cast<IFramebufferLayout*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<IFramebufferLayout::AttachmentLayout> m_renderTargets;
+ bool m_hasDepthStencil = false;
+ IFramebufferLayout::AttachmentLayout m_depthStencil;
+ };
+
+ class FramebufferImpl
+ : public IFramebuffer
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ IFramebuffer* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_IFramebuffer)
+ return static_cast<IFramebuffer*>(this);
+ return nullptr;
+ }
+
+ public:
+ ShortList<RefPtr<RenderTargetViewImpl>, kMaxRTVs> renderTargetViews;
+ ShortList<ID3D11RenderTargetView*, kMaxRTVs> d3dRenderTargetViews;
+ RefPtr<DepthStencilViewImpl> depthStencilView;
+ ID3D11DepthStencilView* d3dDepthStencilView;
+ };
+
+ class SwapchainImpl
+ : public ISwapchain
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+ public:
+ Result init(D3D11Renderer* renderer, const ISwapchain::Desc& desc, WindowHandle window)
+ {
+ // Return fail on non-supported platforms.
+ switch (window.type)
+ {
+ case WindowHandle::Type::Win32Handle:
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+
+ m_renderer = renderer;
+ m_desc = desc;
+
+ // Describe the swap chain.
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = desc.imageCount;
+ swapChainDesc.BufferDesc.Width = desc.width;
+ swapChainDesc.BufferDesc.Height = desc.height;
+ swapChainDesc.BufferDesc.Format = D3DUtil::getMapFormat(desc.format);
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.OutputWindow = (HWND)window.handleValues[0];
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.Windowed = TRUE;
+
+ if (!desc.enableVSync)
+ {
+ swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+ }
+
+ // Swap chain needs the queue so that it can force a flush on it.
+ ComPtr<IDXGISwapChain> swapChain;
+ SLANG_RETURN_ON_FAIL(m_renderer->m_dxgiFactory->CreateSwapChain(
+ m_renderer->m_device, &swapChainDesc, swapChain.writeRef()));
+ SLANG_RETURN_ON_FAIL(swapChain->QueryInterface(m_swapChain.writeRef()));
+
+ if (!desc.enableVSync)
+ {
+ m_swapChainWaitableObject = m_swapChain->GetFrameLatencyWaitableObject();
+
+ int maxLatency = desc.imageCount - 2;
+
+ // 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);
+ }
+
+ SLANG_RETURN_ON_FAIL(m_renderer->m_dxgiFactory->MakeWindowAssociation(
+ (HWND)window.handleValues[0], DXGI_MWA_NO_ALT_ENTER));
+
+ for (uint32_t i = 0; i < desc.imageCount; i++)
+ {
+ ComPtr<ID3D11Resource> d3dResource;
+ m_swapChain->GetBuffer(0, IID_PPV_ARGS(d3dResource.writeRef()));
+ ITextureResource::Desc imageDesc = {};
+ imageDesc.init2D(
+ IResource::Type::Texture2D, desc.format, desc.width, desc.height, 0);
+ RefPtr<TextureResourceImpl> image = new TextureResourceImpl(imageDesc, IResource::Usage::RenderTarget);
+ image->m_resource = d3dResource;
+ m_images.add(image);
+ }
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result
+ getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].Ptr();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result present() override
+ {
+ if (m_swapChainWaitableObject)
+ {
+ // check if now is good time to present
+ // This doesn't wait - because the wait time is 0. If it returns WAIT_TIMEOUT it
+ // means that no frame is waiting to be be displayed so there is no point doing a
+ // present.
+ const bool shouldPresent =
+ (WaitForSingleObjectEx(m_swapChainWaitableObject, 0, TRUE) != WAIT_TIMEOUT);
+ if (shouldPresent)
+ {
+ m_swapChain->Present(0, 0);
+ }
+ }
+ else
+ {
+ if (SLANG_FAILED(m_swapChain->Present(1, 0)))
+ {
+ return SLANG_FAIL;
+ }
+ }
+ return SLANG_OK;
+ }
+
+ virtual SLANG_NO_THROW uint32_t acquireNextImage() override
+ {
+ uint32_t count;
+ m_swapChain->GetLastPresentCount(&count);
+ return count % m_images.getCount();
+ }
+
+ public:
+ D3D11Renderer* m_renderer = nullptr;
+ ISwapchain::Desc m_desc;
+ HANDLE m_swapChainWaitableObject = nullptr;
+ ComPtr<IDXGISwapChain2> m_swapChain;
+ ShortList<RefPtr<TextureResourceImpl>> m_images;
+ };
+
class InputLayoutImpl: public IInputLayout, public RefObject
{
public:
@@ -489,16 +670,6 @@ public:
}
};
- /// Capture a texture to a file
- static HRESULT captureTextureToSurface(
- ID3D11Device* device,
- ID3D11DeviceContext* context,
- TextureResourceImpl* texture,
- void* buffer,
- size_t* inOutBufferSize,
- size_t* outRowPitch,
- size_t* outPixelSize);
-
void _flushGraphicsState();
void _flushComputeState();
@@ -506,21 +677,16 @@ public:
ComPtr<ID3D11Device> m_device;
ComPtr<ID3D11DeviceContext> m_immediateContext;
ComPtr<ID3D11Texture2D> m_backBufferTexture;
+ ComPtr<IDXGIFactory> m_dxgiFactory;
- RefPtr<TextureResourceImpl> m_primaryRenderTargetTexture;
- RefPtr<RenderTargetViewImpl> m_primaryRenderTargetView;
-
-// List<ComPtr<ID3D11RenderTargetView> > m_renderTargetViews;
-// List<ComPtr<ID3D11Texture2D> > m_renderTargetTextures;
-
- bool m_renderTargetBindingsDirty = false;
+ RefPtr<FramebufferImpl> m_currentFramebuffer;
ComPtr<PipelineStateImpl> m_currentPipelineState;
- ComPtr<ID3D11RenderTargetView> m_rtvBindings[kMaxRTVs];
- ComPtr<ID3D11DepthStencilView> m_dsvBinding;
ComPtr<ID3D11UnorderedAccessView> m_uavBindings[int(PipelineType::CountOf)][kMaxUAVs];
- bool m_targetBindingsDirty[int(PipelineType::CountOf)];
+
+ bool m_framebufferBindingDirty = true;
+ bool m_shaderBindingDirty = true;
Desc m_desc;
@@ -529,10 +695,10 @@ public:
bool m_nvapi = false;
};
-SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, void* windowHandle, IRenderer** outRenderer)
+SlangResult SLANG_MCALL createD3D11Renderer(const IRenderer::Desc* desc, IRenderer** outRenderer)
{
RefPtr<D3D11Renderer> result = new D3D11Renderer();
- SLANG_RETURN_ON_FAIL(result->initialize(*desc, windowHandle));
+ SLANG_RETURN_ON_FAIL(result->initialize(*desc));
*outRenderer = result.detach();
return SLANG_OK;
}
@@ -575,87 +741,6 @@ D3D11Renderer::ScopeNVAPI::~ScopeNVAPI()
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!D3D11Renderer !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-/* static */ HRESULT D3D11Renderer::captureTextureToSurface(
- ID3D11Device* device,
- ID3D11DeviceContext* context,
- TextureResourceImpl* texture,
- void* buffer,
- size_t* inOutBufferSize,
- size_t* outRowPitch,
- size_t* outPixelSize)
-{
- if (!context) return E_INVALIDARG;
- if (!texture) return E_INVALIDARG;
-
- // Don't bother supporting MSAA for right now
- if (texture->getDesc()->sampleDesc.numSamples > 1)
- {
- fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
- return E_INVALIDARG;
- }
-
- size_t bytesPerPixel = sizeof(uint32_t);
- size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel;
- size_t bufferSize = rowPitch * int(texture->getDesc()->size.height);
- if (outRowPitch)
- *outRowPitch = rowPitch;
- if (outPixelSize)
- *outPixelSize = bytesPerPixel;
- if (!buffer || *inOutBufferSize == 0)
- {
- *inOutBufferSize = bufferSize;
- return S_OK;
- }
- if (*inOutBufferSize < bufferSize)
- return SLANG_ERROR_INSUFFICIENT_BUFFER;
-
- D3D11_TEXTURE2D_DESC textureDesc;
- auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get());
- d3d11Texture->GetDesc(&textureDesc);
-
- HRESULT hr = S_OK;
- ComPtr<ID3D11Texture2D> stagingTexture;
-
- if (textureDesc.Usage == D3D11_USAGE_STAGING && (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
- {
- stagingTexture = d3d11Texture;
- }
- 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, d3d11Texture);
- }
-
- // 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));
-
- for (size_t y = 0; y < textureDesc.Height; y++)
- {
- memcpy(
- (char*)buffer + y * (*outRowPitch),
- (char*)mappedResource.pData + y * mappedResource.RowPitch,
- *outRowPitch);
- }
- // Make sure to unmap
- context->Unmap(stagingTexture, 0);
- return SLANG_OK;
- }
-}
-
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
static bool _isSupportedNVAPIOp(IUnknown* dev, uint32_t op)
@@ -671,13 +756,12 @@ static bool _isSupportedNVAPIOp(IUnknown* dev, uint32_t op)
#endif
}
-SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
+SlangResult D3D11Renderer::initialize(const Desc& desc)
{
SLANG_RETURN_ON_FAIL(slangContext.initialize(desc.slang, SLANG_DXBC, "sm_5_0"));
- SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc, inWindowHandle));
+ SLANG_RETURN_ON_FAIL(GraphicsAPIRenderer::initialize(desc));
- auto windowHandle = (HWND)inWindowHandle;
m_desc = desc;
// Rather than statically link against D3D, we load it dynamically.
@@ -706,24 +790,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
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;
-
- // 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,
@@ -757,11 +823,13 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
combiner.add(DeviceCheckFlag::UseHardwareDevice, ChangeType::OnOff); ///< First try hardware, then reference
combiner.add(DeviceCheckFlag::UseFullFeatureLevel, ChangeType::OnOff); ///< First try fully featured, then degrade features
+
const int numCombinations = combiner.getNumCombinations();
Result res = SLANG_FAIL;
for (int i = 0; i < numCombinations; ++i)
{
const auto deviceCheckFlags = combiner.getCombination(i);
+ D3DUtil::createFactory(deviceCheckFlags, m_dxgiFactory);
// If we have an adapter set on the desc, look it up. We only need to do so for hardware
ComPtr<IDXGIAdapter> adapter;
@@ -787,36 +855,17 @@ 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;
- 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());
- }
+ 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))
{
@@ -830,7 +879,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
}
// Check we have a swap chain, context and device
SLANG_ASSERT(m_immediateContext && m_device);
- SLANG_ASSERT(!windowHandle || m_swapChain);
}
// NVAPI
@@ -859,68 +907,6 @@ SlangResult D3D11Renderer::initialize(const Desc& desc, void* inWindowHandle)
m_nvapi = true;
#endif
}
-
- // TODO: Add support for debugging to help detect leaks:
- //
- // ComPtr<ID3D11Debug> gDebug;
- // m_device->QueryInterface(IID_PPV_ARGS(gDebug.writeRef()));
- //
-
- // 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 };
- if (m_swapChain)
- {
- 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()));
-
- 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_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;
}
@@ -931,42 +917,146 @@ void D3D11Renderer::setClearColor(const float color[4])
void D3D11Renderer::clearFrame()
{
- m_immediateContext->ClearRenderTargetView(m_primaryRenderTargetView->m_rtv, m_clearColor);
+ for (auto rtv : m_currentFramebuffer->renderTargetViews)
+ m_immediateContext->ClearRenderTargetView(rtv->m_rtv, m_clearColor);
- if(m_dsvBinding)
+ if (m_currentFramebuffer->depthStencilView)
{
- m_immediateContext->ClearDepthStencilView(m_dsvBinding, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
+ m_immediateContext->ClearDepthStencilView(
+ m_currentFramebuffer->depthStencilView->m_dsv,
+ D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,
+ 1.0f,
+ 0);
}
}
-void D3D11Renderer::presentFrame()
+void D3D11Renderer::beginFrame() { }
+
+void D3D11Renderer::endFrame() {}
+
+Result D3D11Renderer::createSwapchain(
+ const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
- m_immediateContext->CopyResource(m_backBufferTexture, m_primaryRenderTargetTexture->m_resource);
- m_swapChain->Present(0, 0);
+ RefPtr<SwapchainImpl> swapchain = new SwapchainImpl();
+ SLANG_RETURN_ON_FAIL(swapchain->init(this, desc, window));
+ *outSwapchain = swapchain.detach();
+ return SLANG_OK;
}
-TextureResource::Desc D3D11Renderer::getSwapChainTextureDesc()
+Result D3D11Renderer::createFramebufferLayout(
+ const IFramebufferLayout::Desc& desc, IFramebufferLayout** outLayout)
{
- D3D11_TEXTURE2D_DESC dxDesc;
- ((ID3D11Texture2D*)m_primaryRenderTargetTexture->m_resource.get())->GetDesc(&dxDesc);
+ RefPtr<FramebufferLayoutImpl> layout = new FramebufferLayoutImpl();
+ layout->m_renderTargets.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ layout->m_renderTargets[i] = desc.renderTargets[i];
+ }
- TextureResource::Desc desc;
- desc.init2D(IResource::Type::Texture2D, Format::Unknown, dxDesc.Width, dxDesc.Height, 1);
+ if (desc.depthStencil)
+ {
+ layout->m_hasDepthStencil = true;
+ layout->m_depthStencil = *desc.depthStencil;
+ }
+ else
+ {
+ layout->m_hasDepthStencil = false;
+ }
+ *outLayout = layout.detach();
+ return SLANG_OK;
+}
+
+Result D3D11Renderer::createFramebuffer(
+ const IFramebuffer::Desc& desc, IFramebuffer** outFramebuffer)
+{
+ RefPtr<FramebufferImpl> framebuffer = new FramebufferImpl();
+ framebuffer->renderTargetViews.setCount(desc.renderTargetCount);
+ framebuffer->d3dRenderTargetViews.setCount(desc.renderTargetCount);
+ for (uint32_t i = 0; i < desc.renderTargetCount; i++)
+ {
+ framebuffer->renderTargetViews[i] = static_cast<RenderTargetViewImpl*>(desc.renderTargetViews[i]);
+ framebuffer->d3dRenderTargetViews[i] = framebuffer->renderTargetViews[i]->m_rtv;
+ }
+ framebuffer->depthStencilView = static_cast<DepthStencilViewImpl*>(desc.depthStencilView);
+ framebuffer->d3dDepthStencilView = framebuffer->depthStencilView->m_dsv;
+ *outFramebuffer = framebuffer.detach();
+ return SLANG_OK;
+}
- return desc;
+void D3D11Renderer::setFramebuffer(IFramebuffer* frameBuffer)
+{
+ m_framebufferBindingDirty = true;
+ m_currentFramebuffer = static_cast<FramebufferImpl*>(frameBuffer);
}
-SlangResult D3D11Renderer::captureScreenSurface(
- void* buffer, size_t* inOutBufferSize, size_t* outRowPitch, size_t* outPixelSize)
+SlangResult D3D11Renderer::readTextureResource(
+ ITextureResource* resource, ISlangBlob** outBlob, size_t* outRowPitch, size_t* outPixelSize)
{
- return captureTextureToSurface(
- m_device,
- m_immediateContext,
- m_primaryRenderTargetTexture.Ptr(),
- buffer,
- inOutBufferSize,
- outRowPitch,
- outPixelSize);
+ auto texture = static_cast<TextureResourceImpl*>(resource);
+ // Don't bother supporting MSAA for right now
+ if (texture->getDesc()->sampleDesc.numSamples > 1)
+ {
+ fprintf(stderr, "ERROR: cannot capture multi-sample texture\n");
+ return E_INVALIDARG;
+ }
+
+ size_t bytesPerPixel = sizeof(uint32_t);
+ size_t rowPitch = int(texture->getDesc()->size.width) * bytesPerPixel;
+ size_t bufferSize = rowPitch * int(texture->getDesc()->size.height);
+ if (outRowPitch)
+ *outRowPitch = rowPitch;
+ if (outPixelSize)
+ *outPixelSize = bytesPerPixel;
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ auto d3d11Texture = ((ID3D11Texture2D*)texture->m_resource.get());
+ d3d11Texture->GetDesc(&textureDesc);
+
+ HRESULT hr = S_OK;
+ ComPtr<ID3D11Texture2D> stagingTexture;
+
+ if (textureDesc.Usage == D3D11_USAGE_STAGING &&
+ (textureDesc.CPUAccessFlags & D3D11_CPU_ACCESS_READ))
+ {
+ stagingTexture = d3d11Texture;
+ }
+ 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 = m_device->CreateTexture2D(&textureDesc, 0, stagingTexture.writeRef());
+ if (FAILED(hr))
+ {
+ fprintf(stderr, "ERROR: failed to create staging texture\n");
+ return hr;
+ }
+
+ m_immediateContext->CopyResource(stagingTexture, d3d11Texture);
+ }
+
+ // Now just read back texels from the staging textures
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ SLANG_RETURN_ON_FAIL(m_immediateContext->Map(stagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource));
+ RefPtr<ListBlob> blob = new ListBlob();
+ blob->m_data.setCount(bufferSize);
+ char* buffer = (char*)blob->m_data.begin();
+ for (size_t y = 0; y < textureDesc.Height; y++)
+ {
+ memcpy(
+ (char*)buffer + y * (*outRowPitch),
+ (char*)mappedResource.pData + y * mappedResource.RowPitch,
+ *outRowPitch);
+ }
+ // Make sure to unmap
+ m_immediateContext->Unmap(stagingTexture, 0);
+ *outBlob = blob.detach();
+ return SLANG_OK;
+ }
}
static D3D11_BIND_FLAG _calcResourceFlag(IResource::BindFlag::Enum bindFlag)
@@ -1661,12 +1751,6 @@ void D3D11Renderer::setIndexBuffer(IBufferResource* buffer, Format indexFormat,
m_immediateContext->IASetIndexBuffer(((BufferResourceImpl*)buffer)->m_buffer, dxFormat, UINT(offset));
}
-void D3D11Renderer::setDepthStencilTarget(IResourceView* depthStencilView)
-{
- m_dsvBinding = ((DepthStencilViewImpl*) depthStencilView)->m_dsv;
- m_targetBindingsDirty[int(PipelineType::Graphics)] = true;
-}
-
void D3D11Renderer::setViewports(UInt count, Viewport const* viewports)
{
static const int kMaxViewports = D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX + 1;
@@ -2097,9 +2181,10 @@ Result D3D11Renderer::createGraphicsPipelineState(const GraphicsPipelineStateDes
state->m_depthStencilState = depthStencilState;
state->m_rasterizerState = rasterizerState;
state->m_blendState = blendState;
- state->m_pipelineLayout = (PipelineLayoutImpl*) desc.pipelineLayout;
- state->m_inputLayout = (InputLayoutImpl*) desc.inputLayout;
- state->m_rtvCount = UINT(desc.renderTargetCount);
+ state->m_pipelineLayout = static_cast<PipelineLayoutImpl*>(desc.pipelineLayout);
+ state->m_inputLayout = static_cast<InputLayoutImpl*>(desc.inputLayout);
+ state->m_rtvCount = (UINT) static_cast<FramebufferLayoutImpl*>(desc.framebufferLayout)
+ ->m_renderTargets.getCount();
state->m_blendColor[0] = 0;
state->m_blendColor[1] = 0;
state->m_blendColor[2] = 0;
@@ -2258,8 +2343,10 @@ Result D3D11Renderer::createPipelineLayout(const IPipelineLayout::Desc& desc, IP
return SLANG_OK;
}
-Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet** outDescriptorSet)
+Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescriptorSet::Flag::Enum flag, IDescriptorSet** outDescriptorSet)
{
+ SLANG_UNUSED(flag);
+
auto layoutImpl = (DescriptorSetLayoutImpl*)layout;
RefPtr<DescriptorSetImpl> descriptorSetImpl = new DescriptorSetImpl();
@@ -2321,19 +2408,19 @@ Result D3D11Renderer::createDescriptorSet(IDescriptorSetLayout* layout, IDescrip
void D3D11Renderer::_flushGraphicsState()
{
auto pipelineType = int(PipelineType::Graphics);
- if(m_targetBindingsDirty[pipelineType])
+ if (m_framebufferBindingDirty || m_shaderBindingDirty)
{
- m_targetBindingsDirty[pipelineType] = false;
+ m_framebufferBindingDirty = false;
+ m_shaderBindingDirty = false;
auto pipelineState = static_cast<GraphicsPipelineStateImpl*>(m_currentPipelineState.get());
- auto rtvCount = pipelineState->m_rtvCount;
+ auto rtvCount = (UINT)m_currentFramebuffer->renderTargetViews.getCount();
auto uavCount = pipelineState->m_pipelineLayout->m_uavCount;
-
m_immediateContext->OMSetRenderTargetsAndUnorderedAccessViews(
rtvCount,
- m_rtvBindings[0].readRef(),
- m_dsvBinding,
+ m_currentFramebuffer->d3dRenderTargetViews.getArrayView().getBuffer(),
+ m_currentFramebuffer->d3dDepthStencilView,
rtvCount,
uavCount,
m_uavBindings[pipelineType][0].readRef(),
@@ -2344,9 +2431,9 @@ void D3D11Renderer::_flushGraphicsState()
void D3D11Renderer::_flushComputeState()
{
auto pipelineType = int(PipelineType::Compute);
- if(m_targetBindingsDirty[pipelineType])
+ if (m_shaderBindingDirty)
{
- m_targetBindingsDirty[pipelineType] = false;
+ m_shaderBindingDirty = false;
auto pipelineState = static_cast<ComputePipelineStateImpl*>(m_currentPipelineState.get());
@@ -2568,7 +2655,7 @@ void D3D11Renderer::setDescriptorSet(PipelineType pipelineType, IPipelineLayout*
{
m_uavBindings[int(pipelineType)][startSlot + ii] = uavs[ii];
}
- m_targetBindingsDirty[int(pipelineType)] = true;
+ m_shaderBindingDirty = true;
}
}
}