summaryrefslogtreecommitdiff
path: root/tools/gfx/d3d
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-10 10:58:15 -0800
committerGitHub <noreply@github.com>2021-03-10 10:58:15 -0800
commit6ef4054f8a8aea4ec61481057fa7e16aaecde6d7 (patch)
tree66edcae112faff7276c2595865463698bde277fd /tools/gfx/d3d
parent2765861cdc104e6104a31cf9e20800b8d1dfae26 (diff)
Swapchain resize and rename to `IDevice` (#1741)
* Swapchain resize * Fix.
Diffstat (limited to 'tools/gfx/d3d')
-rw-r--r--tools/gfx/d3d/d3d-swapchain.cpp0
-rw-r--r--tools/gfx/d3d/d3d-swapchain.h154
2 files changed, 154 insertions, 0 deletions
diff --git a/tools/gfx/d3d/d3d-swapchain.cpp b/tools/gfx/d3d/d3d-swapchain.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tools/gfx/d3d/d3d-swapchain.cpp
diff --git a/tools/gfx/d3d/d3d-swapchain.h b/tools/gfx/d3d/d3d-swapchain.h
new file mode 100644
index 000000000..5a9ead876
--- /dev/null
+++ b/tools/gfx/d3d/d3d-swapchain.h
@@ -0,0 +1,154 @@
+#pragma once
+
+#include "slang-gfx.h"
+#include "core/slang-basic.h"
+#include <dxgi1_4.h>
+#include "../renderer-shared.h"
+#include "d3d-util.h"
+
+namespace gfx
+{
+class D3DSwapchainBase
+ : public ISwapchain
+ , public Slang::RefObject
+{
+public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ISwapchain* getInterface(const Slang::Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ISwapchain)
+ return static_cast<ISwapchain*>(this);
+ return nullptr;
+ }
+
+public:
+ Result init(const ISwapchain::Desc& desc, WindowHandle window, DXGI_SWAP_EFFECT swapEffect)
+ {
+ // Return fail on non-supported platforms.
+ switch (window.type)
+ {
+ case WindowHandle::Type::Win32Handle:
+ break;
+ default:
+ return SLANG_FAIL;
+ }
+
+ 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 = swapEffect;
+ 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(
+ getDXGIFactory()->CreateSwapChain(getOwningDevice(), &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 dx 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(getDXGIFactory()->MakeWindowAssociation(
+ (HWND)window.handleValues[0], DXGI_MWA_NO_ALT_ENTER));
+
+ createSwapchainBufferImages();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ getImage(uint32_t index, ITextureResource** outResource) override
+ {
+ m_images[index]->addRef();
+ *outResource = m_images[index].get();
+ return SLANG_OK;
+ }
+ virtual SLANG_NO_THROW Result SLANG_MCALL 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 int SLANG_MCALL acquireNextImage() override
+ {
+ uint32_t count;
+ m_swapChain->GetLastPresentCount(&count);
+ return (int)(count % m_desc.imageCount);
+ }
+
+
+ virtual SLANG_NO_THROW Result SLANG_MCALL resize(uint32_t width, uint32_t height) override
+ {
+ if (width == m_desc.width && height == m_desc.height)
+ return SLANG_OK;
+
+ m_desc.width = width;
+ m_desc.height = height;
+ for (auto& image : m_images)
+ image = nullptr;
+ m_images.clear();
+ auto result = m_swapChain->ResizeBuffers(
+ m_desc.imageCount,
+ width,
+ height,
+ D3DUtil::getMapFormat(m_desc.format),
+ m_desc.enableVSync ? 0 : DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT);
+ if (result != 0)
+ return SLANG_FAIL;
+ createSwapchainBufferImages();
+ return SLANG_OK;
+ }
+
+public:
+ virtual void createSwapchainBufferImages() = 0;
+ virtual IDXGIFactory* getDXGIFactory() = 0;
+ virtual IUnknown* getOwningDevice() = 0;
+ ISwapchain::Desc m_desc;
+ HANDLE m_swapChainWaitableObject = nullptr;
+ ComPtr<IDXGISwapChain2> m_swapChain;
+ Slang::ShortList<ComPtr<ITextureResource>> m_images;
+};
+
+}