From bc84471d4ddcaddb8345cf2e0b10a1e643268db9 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 3 Nov 2015 14:27:32 -1000 Subject: [PATCH] More D3D12 work --- include/boo/graphicsdev/D3D12.hpp | 1 + .../boo/graphicsdev/IGraphicsCommandQueue.hpp | 5 +- .../boo/graphicsdev/IGraphicsDataFactory.hpp | 31 +- lib/graphicsdev/D3D12.cpp | 264 +++++++++++++----- lib/win/ApplicationWin32.cpp | 21 +- lib/win/Win32Common.hpp | 19 +- lib/win/WindowWin32.cpp | 46 ++- 7 files changed, 293 insertions(+), 94 deletions(-) diff --git a/include/boo/graphicsdev/D3D12.hpp b/include/boo/graphicsdev/D3D12.hpp index 11a6654..57361ad 100644 --- a/include/boo/graphicsdev/D3D12.hpp +++ b/include/boo/graphicsdev/D3D12.hpp @@ -35,6 +35,7 @@ public: ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); + ITextureR* newRenderTexture(size_t width, size_t height, size_t samples); IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); diff --git a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp index a555b34..0c43cff 100644 --- a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp +++ b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp @@ -21,8 +21,7 @@ struct IGraphicsCommandQueue virtual const char* platformName() const=0; virtual void setShaderDataBinding(IShaderDataBinding* binding)=0; - virtual void setRenderTarget(IWindow* window)=0; - virtual void setRenderTarget(ITextureD* target)=0; + virtual void setRenderTarget(ITextureR* target)=0; virtual void setViewport(const SWindowRect& rect)=0; virtual void setClearColor(const float rgba[4])=0; @@ -34,7 +33,7 @@ struct IGraphicsCommandQueue virtual void drawInstances(size_t start, size_t count, size_t instCount)=0; virtual void drawInstancesIndexed(size_t start, size_t count, size_t instCount)=0; - virtual void present()=0; + virtual void resolveDisplay(ITextureR* source)=0; virtual void execute()=0; }; diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 122bda1..5eefa3c 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -41,19 +41,31 @@ enum BufferUse BufferUseUniform }; +enum TextureType +{ + TextureStatic, + Texture +}; + struct ITexture { - bool dynamic() const {return m_dynamic;} + enum Type + { + TextureStatic, + TextureDynamic, + TextureRender + }; + Type type() const {return m_type;} protected: - bool m_dynamic; - ITexture(bool dynamic) : m_dynamic(dynamic) {} + Type m_type; + ITexture(Type type) : m_type(type) {} }; /** Static resource buffer for textures */ struct ITextureS : ITexture { protected: - ITextureS() : ITexture(false) {} + ITextureS() : ITexture(TextureStatic) {} }; /** Dynamic resource buffer for textures */ @@ -63,7 +75,14 @@ struct ITextureD : ITexture virtual void* map(size_t sz)=0; virtual void unmap()=0; protected: - ITextureD() : ITexture(true) {} + ITextureD() : ITexture(TextureDynamic) {} +}; + +/** Resource buffer for render-target textures */ +struct ITextureR : ITexture +{ +protected: + ITextureR() : ITexture(TextureRender) {} }; /** Supported texture formats */ @@ -157,6 +176,8 @@ struct IGraphicsDataFactory const void* data, size_t sz)=0; virtual ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; + virtual ITextureR* + newRenderTexture(size_t width, size_t height, size_t samples)=0; virtual IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0; diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index d06129c..c2b12ab 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -38,6 +38,7 @@ struct D3D12Data : IGraphicsData std::vector> m_DBufs; std::vector> m_STexs; std::vector> m_DTexs; + std::vector> m_RTexs; std::vector> m_VFmts; ComPtr m_gpuHeap; }; @@ -94,7 +95,7 @@ class D3D12GraphicsBufferD : public IGraphicsBufferD : m_state(USE_TABLE[use]), m_q(q), m_stride(stride), m_count(count) { size_t sz = stride * count; - for (int i=0 ; i<3 ; ++i) + for (int i=0 ; i<2 ; ++i) { ThrowIfFailed(ctx->m_dev->CreateCommittedResource( &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), @@ -105,8 +106,8 @@ class D3D12GraphicsBufferD : public IGraphicsBufferD public: size_t m_stride; size_t m_count; - ComPtr m_bufs[3]; - ComPtr m_gpuBufs[3]; + ComPtr m_bufs[2]; + ComPtr m_gpuBufs[2]; ~D3D12GraphicsBufferD() = default; void load(const void* data, size_t sz); @@ -115,7 +116,7 @@ public: UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) { - for (int i=0 ; i<3 ; ++i) + for (int i=0 ; i<2 ; ++i) { D3D12_RESOURCE_DESC desc = m_bufs[i]->GetDesc(); ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, m_state, @@ -185,39 +186,22 @@ class D3D12TextureD : public ITextureD D3D12TextureD(D3D12CommandQueue* q, D3D12Context* ctx, size_t width, size_t height, TextureFormat fmt) : m_q(q) { - ThrowIfFailed(ctx->m_dev->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), - D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_texs[0])); - ThrowIfFailed(ctx->m_dev->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), - D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_texs[1])); + for (int i=0 ; i<2 ; ++i) + { + ThrowIfFailed(ctx->m_dev->CreateCommittedResource( + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), + D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, __uuidof(ID3D12Resource), &m_texs[i])); + } } public: ComPtr m_texs[2]; ComPtr m_gpuTexs[2]; - ComPtr m_rtvHeap; - ComPtr m_dsvHeap; ~D3D12TextureD() = default; - void load(const void* data, size_t sz) - { - void* buf; - m_texs[0]->Map(0, nullptr, &buf); - memcpy(buf, data, sz); - m_texs[0]->Unmap(0, nullptr); - } - void* map(size_t sz) - { - void* buf; - m_texs[0]->Map(0, nullptr, &buf); - return buf; - } - void unmap() - { - m_texs[0]->Unmap(0, nullptr); - } + void load(const void* data, size_t sz); + void* map(size_t sz); + void unmap(); UINT64 placeForGPU(D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) { @@ -225,10 +209,39 @@ public: { D3D12_RESOURCE_DESC desc = m_texs[i]->GetDesc(); ThrowIfFailed(ctx->m_dev->CreatePlacedResource(gpuHeap, offset, &desc, - i ? D3D12_RESOURCE_STATE_DEPTH_WRITE : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, __uuidof(ID3D12Resource), &m_gpuTexs[i])); offset = NextHeapOffset(offset, ctx->m_dev->GetResourceAllocationInfo(0, 1, &desc)); } + return offset; + } +}; + +static const float BLACK_COLOR[] = {0.0,0.0,0.0,1.0}; + +class D3D12TextureR : public ITextureR +{ + friend class D3D12DataFactory; + friend struct D3D12CommandQueue; + size_t m_width = 0; + size_t m_height = 0; + size_t m_samples = 0; + D3D12TextureR(D3D12Context* ctx, size_t width, size_t height, size_t samples) + : m_width(width), m_height(height), m_samples(samples) + { + if (samples == 0) m_samples = 1; + + CD3DX12_RESOURCE_DESC rtvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_width, m_height, 1, 0, m_samples, + 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); + ThrowIfFailed(ctx->m_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, + &rtvresdesc, D3D12_RESOURCE_STATE_RENDER_TARGET, &CD3DX12_CLEAR_VALUE(DXGI_FORMAT_R8G8B8A8_UNORM, BLACK_COLOR), + __uuidof(ID3D12Resource), &m_gpuTexs[0])); + + CD3DX12_RESOURCE_DESC dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, m_width, m_height, 1, 0, m_samples, + 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); + ThrowIfFailed(ctx->m_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, + &dsvresdesc, D3D12_RESOURCE_STATE_DEPTH_WRITE, &CD3DX12_CLEAR_VALUE(DXGI_FORMAT_D24_UNORM_S8_UINT, 1.0, 0), + __uuidof(ID3D12Resource), &m_gpuTexs[1])); D3D12_DESCRIPTOR_HEAP_DESC rtvdesc = {D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1}; ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&rtvdesc, __uuidof(ID3D12DescriptorHeap), &m_rtvHeap)); @@ -239,9 +252,12 @@ public: ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&dsvdesc, __uuidof(ID3D12DescriptorHeap), &m_dsvHeap)); D3D12_DEPTH_STENCIL_VIEW_DESC dsvvdesc = {DXGI_FORMAT_D24_UNORM_S8_UINT, D3D12_DSV_DIMENSION_TEXTURE2D}; ctx->m_dev->CreateDepthStencilView(m_gpuTexs[1].Get(), &dsvvdesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); - - return offset; } +public: + ComPtr m_gpuTexs[2]; + ComPtr m_rtvHeap; + ComPtr m_dsvHeap; + ~D3D12TextureR() = default; }; ITextureS* @@ -397,9 +413,9 @@ static UINT64 PlaceBufferForGPU(IGraphicsBuffer* buf, D3D12Context* ctx, ID3D12H static UINT64 PlaceTextureForGPU(ITexture* tex, D3D12Context* ctx, ID3D12Heap* gpuHeap, UINT64 offset) { - if (tex->dynamic()) + if (tex->type() == ITexture::TextureDynamic) return static_cast(tex)->placeForGPU(ctx, gpuHeap, offset); - else + else if (tex->type() == ITexture::TextureStatic) return static_cast(tex)->placeForGPU(ctx, gpuHeap, offset); } @@ -429,12 +445,12 @@ static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, static ID3D12Resource* GetTextureGPUResource(const ITexture* tex, int idx) { - if (tex->dynamic()) + if (tex->type() == ITexture::TextureDynamic) { const D3D12TextureD* ctex = static_cast(tex); return ctex->m_gpuTexs[0].Get(); } - else + else if (tex->type() == ITexture::TextureStatic) { const D3D12TextureS* ctex = static_cast(tex); return ctex->m_gpuTex.Get(); @@ -456,7 +472,7 @@ struct D3D12ShaderDataBinding : IShaderDataBinding { D3D12ShaderPipeline* m_pipeline; ComPtr m_gpuHeap; - ComPtr m_descHeap[3]; + ComPtr m_descHeap[2]; IGraphicsBuffer* m_vbuf; IGraphicsBuffer* m_ibuf; size_t m_ubufCount; @@ -484,7 +500,7 @@ struct D3D12ShaderDataBinding : IShaderDataBinding void commit(D3D12Context* ctx) { - /* Create triple-buffered descriptor heaps */ + /* Create double-buffered descriptor heaps */ D3D12_DESCRIPTOR_HEAP_DESC desc; desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; desc.NumDescriptors = 2 + m_ubufCount + m_texCount; @@ -492,7 +508,7 @@ struct D3D12ShaderDataBinding : IShaderDataBinding desc.NodeMask = 0; UINT incSz = ctx->m_dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - for (int b=0 ; b<3 ; ++b) + for (int b=0 ; b<2 ; ++b) { ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&desc, _uuidof(ID3D12DescriptorHeap), &m_descHeap[b])); CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart()); @@ -561,7 +577,7 @@ IGraphicsData* D3D12DataFactory::commit() /* Gather resource descriptions */ std::vector descs; - descs.reserve(retval->m_SBufs.size() + retval->m_DBufs.size() * 3 + + descs.reserve(retval->m_SBufs.size() + retval->m_DBufs.size() * 2 + retval->m_STexs.size() + retval->m_DTexs.size() * 2); for (std::unique_ptr& buf : retval->m_SBufs) @@ -571,7 +587,6 @@ IGraphicsData* D3D12DataFactory::commit() { descs.push_back(buf->m_bufs[0]->GetDesc()); descs.push_back(buf->m_bufs[1]->GetDesc()); - descs.push_back(buf->m_bufs[2]->GetDesc()); } for (std::unique_ptr& tex : retval->m_STexs) @@ -581,7 +596,6 @@ IGraphicsData* D3D12DataFactory::commit() { descs.push_back(tex->m_texs[0]->GetDesc()); descs.push_back(tex->m_texs[1]->GetDesc()); - descs.push_back(tex->m_texs[2]->GetDesc()); } /* Calculate resources allocation */ @@ -636,19 +650,29 @@ struct D3D12CommandQueue : IGraphicsCommandQueue Platform platform() const {return IGraphicsDataFactory::PlatformD3D12;} const char* platformName() const {return "Direct 3D 12";} D3D12Context* m_ctx; + D3D12Context::Window* m_windowCtx; IGraphicsContext* m_parent; ComPtr m_cmdList; size_t m_fillBuf = 0; - size_t m_completeBuf = 0; size_t m_drawBuf = 0; - D3D12CommandQueue(D3D12Context* ctx, IGraphicsContext* parent) - : m_ctx(ctx), m_parent(parent) + void resetCommandList() + { + ThrowIfFailed(m_ctx->m_qalloc[m_fillBuf]->Reset()); + ThrowIfFailed(m_cmdList->Reset(m_ctx->m_qalloc[m_fillBuf].Get(), nullptr)); + m_cmdList->SetGraphicsRootSignature(m_ctx->m_rs.Get()); + } + + D3D12CommandQueue(D3D12Context* ctx, D3D12Context::Window* windowCtx, IGraphicsContext* parent) + : m_ctx(ctx), m_windowCtx(windowCtx), m_parent(parent) { ThrowIfFailed(ctx->m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), - &ctx->m_qalloc)); + &ctx->m_qalloc[0])); + ThrowIfFailed(ctx->m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, + __uuidof(ID3D12CommandAllocator), + &ctx->m_qalloc[1])); D3D12_COMMAND_QUEUE_DESC desc = { D3D12_COMMAND_LIST_TYPE_DIRECT, @@ -658,7 +682,7 @@ struct D3D12CommandQueue : IGraphicsCommandQueue ThrowIfFailed(ctx->m_dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), &ctx->m_q)); ThrowIfFailed(ctx->m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), &ctx->m_frameFence)); - ThrowIfFailed(ctx->m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, ctx->m_qalloc.Get(), + ThrowIfFailed(ctx->m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, ctx->m_qalloc[0].Get(), nullptr, __uuidof(ID3D12GraphicsCommandList), &m_cmdList)); m_cmdList->SetGraphicsRootSignature(m_ctx->m_rs.Get()); } @@ -671,19 +695,13 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_cmdList->SetPipelineState(cbind->m_pipeline->m_state.Get()); } - D3D12TextureD* m_boundTarget = nullptr; - - void setRenderTarget(IWindow* window) + ID3D12Resource* m_boundTarget = nullptr; + void setRenderTarget(ITextureR* target) { - - } - - void setRenderTarget(ITextureD* target) - { - D3D12TextureD* ctarget = static_cast(target); + D3D12TextureR* ctarget = static_cast(target); if (m_boundTarget) - m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_boundTarget->m_gpuTexs[0].Get(), + m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_boundTarget, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); m_cmdList->OMSetRenderTargets(1, &ctarget->m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), @@ -692,12 +710,13 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ctarget->m_gpuTexs[0].Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); - m_boundTarget = ctarget; + m_boundTarget = ctarget->m_gpuTexs[0].Get(); } void setViewport(const SWindowRect& rect) { - + D3D12_VIEWPORT vp = {rect.location[0], rect.location[1], rect.size[0], rect.size[1], 0.0, 1.0}; + m_cmdList->RSSetViewports(1, &vp); } float m_clearColor[4] = {0.0,0.0,0.0,1.0}; @@ -751,21 +770,90 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_cmdList->DrawIndexedInstanced(count, instCount, start, 0, 0); } - void present() + bool m_doPresent = false; + void resolveDisplay(ITextureR* source) { - m_cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); + D3D12TextureR* csource = static_cast(source); + + ID3D12Resource* src = csource->m_gpuTexs[0].Get(); + ID3D12Resource* dest = m_windowCtx->m_fb[m_windowCtx->m_backBuf].Get(); + + if (csource->m_samples > 1) + { + D3D12_RESOURCE_BARRIER msaaSetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition(dest, + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST) + }; + m_cmdList->ResourceBarrier(2, msaaSetup); + + m_cmdList->ResolveSubresource(dest, 0, src, 0, DXGI_FORMAT_R8G8B8A8_UNORM); + + D3D12_RESOURCE_BARRIER msaaTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(dest, + D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(2, msaaTeardown); + } + else + { + D3D12_RESOURCE_BARRIER copySetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition(dest, + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) + }; + m_cmdList->ResourceBarrier(2, copySetup); + + m_cmdList->CopyResource(dest, src); + + D3D12_RESOURCE_BARRIER copyTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET), + CD3DX12_RESOURCE_BARRIER::Transition(dest, + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(2, copyTeardown); + } + m_doPresent = true; } + UINT64 m_submittedFenceVal = 0; void execute() { - m_completeBuf = m_fillBuf; - for (size_t i=0 ; i<3 ; ++i) + /* Check on fence */ + if (m_ctx->m_frameFence->GetCompletedValue() < m_submittedFenceVal) { - if (i == m_completeBuf || i == m_drawBuf) - continue; - m_fillBuf = i; - break; + resetCommandList(); + return; } + + m_drawBuf = m_fillBuf; + ++m_fillBuf; + if (m_fillBuf == 2) + m_fillBuf = 0; + + m_cmdList->Close(); + ID3D12CommandList* cl[] = {m_cmdList.Get()}; + m_ctx->m_q->ExecuteCommandLists(1, cl); + + if (m_doPresent) + { + ThrowIfFailed(m_windowCtx->m_swapChain->Present(1, 0)); + m_windowCtx->m_backBuf = m_windowCtx->m_swapChain->GetCurrentBackBufferIndex(); + } + + ++m_submittedFenceVal; + ThrowIfFailed(m_ctx->m_q->Signal(m_ctx->m_frameFence.Get(), m_submittedFenceVal)); + + resetCommandList(); } }; @@ -799,27 +887,57 @@ D3D12DataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) return retval; } +void D3D12TextureD::load(const void* data, size_t sz) +{ + ID3D12Resource* res = m_texs[m_q->m_fillBuf].Get(); + void* d; + res->Map(0, nullptr, &d); + memcpy(d, data, sz); + res->Unmap(0, nullptr); +} +void* D3D12TextureD::map(size_t sz) +{ + ID3D12Resource* res = m_texs[m_q->m_fillBuf].Get(); + void* d; + res->Map(0, nullptr, &d); + return d; +} +void D3D12TextureD::unmap() +{ + ID3D12Resource* res = m_texs[m_q->m_fillBuf].Get(); + res->Unmap(0, nullptr); +} + ITextureD* D3D12DataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); - D3D12TextureD* retval = new D3D12TextureD(q, width, height, fmt); + D3D12TextureD* retval = new D3D12TextureD(q, m_ctx, width, height, fmt); static_cast(m_deferredData)->m_DTexs.emplace_back(retval); return retval; } +ITextureR* +D3D12DataFactory::newRenderTexture(size_t width, size_t height, size_t samples) +{ + D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); + D3D12TextureR* retval = new D3D12TextureR(m_ctx, width, height, samples); + static_cast(m_deferredData)->m_RTexs.emplace_back(retval); + return retval; +} + IVertexFormat* D3D12DataFactory::newVertexFormat (size_t elementCount, const VertexElementDescriptor* elements) { D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); - D3D12VertexFormat* retval = new struct D3D12VertexFormat(q, elementCount, elements); + D3D12VertexFormat* retval = new struct D3D12VertexFormat(elementCount, elements); static_cast(m_deferredData)->m_VFmts.emplace_back(retval); return retval; } -IGraphicsCommandQueue* _NewD3D12CommandQueue(D3D12Context* ctx, IGraphicsContext* parent) +IGraphicsCommandQueue* _NewD3D12CommandQueue(D3D12Context* ctx, D3D12Context::Window* windowCtx, IGraphicsContext* parent) { - return new struct D3D12CommandQueue(ctx, parent); + return new struct D3D12CommandQueue(ctx, windowCtx, parent); } } diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index 002bd64..d05f381 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -4,10 +4,8 @@ #include #if _DEBUG -#define DXGI_FACTORY2_FLAGS DXGI_CREATE_FACTORY_DEBUG #define D3D11_CREATE_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG #else -#define DXGI_FACTORY2_FLAGS 0 #define D3D11_CREATE_DEVICE_FLAGS 0 #endif @@ -65,18 +63,26 @@ public: if (!MyCreateDXGIFactory2) Log.report(LogVisor::FatalError, "unable to find CreateDXGIFactory2 in DXGI.dll\n" "Windows 7 users should install \"Platform Update for Windows 7\" from Microsoft"); - if (FAILED(MyCreateDXGIFactory2(DXGI_FACTORY2_FLAGS, __uuidof(IDXGIFactory2), &m_d3dCtx.m_dxFactory))) - Log.report(LogVisor::FatalError, "unable to create DXGI factory"); #if WINVER >= _WIN32_WINNT_WIN10 HMODULE d3d12lib = LoadLibraryW(L"D3D12.dll"); if (d3d12lib) { + /* Create device */ PFN_D3D12_CREATE_DEVICE MyD3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(d3d12lib, "D3D12CreateDevice"); if (!MyD3D12CreateDevice) Log.report(LogVisor::FatalError, "unable to find D3D12CreateDevice in D3D12.dll"); + + /* Create device */ if (FAILED(MyD3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_12_0, __uuidof(ID3D12Device), &m_d3dCtx.m_ctx12.m_dev))) Log.report(LogVisor::FatalError, "unable to create D3D12 device"); + + /* Obtain DXGI Factory */ + ComPtr device; + ComPtr adapter; + m_d3dCtx.m_ctx12.m_dev.As(&device); + device->GetParent(__uuidof(IDXGIAdapter), &adapter); + adapter->GetParent(__uuidof(IDXGIFactory2), &m_d3dCtx.m_dxFactory); return; } @@ -99,6 +105,13 @@ public: tempDev.As(&m_d3dCtx.m_ctx11.m_dev); tempCtx.As(&m_d3dCtx.m_ctx11.m_devCtx); + /* Obtain DXGI Factory */ + ComPtr device; + ComPtr adapter; + m_d3dCtx.m_ctx11.m_dev.As(&device); + device->GetParent(__uuidof(IDXGIAdapter), &adapter); + adapter->GetParent(__uuidof(IDXGIFactory2), &m_d3dCtx.m_dxFactory); + return; } diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index 7e5db88..80cea7b 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -8,6 +8,9 @@ #define WIN32_LEAN_AND_MEAN 1 #endif #include +#include + +namespace boo {class IWindow;} #if _WIN32_WINNT_WIN10 #include @@ -17,12 +20,20 @@ struct D3D12Context { ComPtr m_dev; - ComPtr m_qalloc; + ComPtr m_qalloc[2]; ComPtr m_q; ComPtr m_loadqalloc; ComPtr m_loadq; ComPtr m_frameFence; ComPtr m_rs; + struct Window + { + ComPtr m_swapChain; + ComPtr m_fb[2]; /* Double-buffered */ + UINT m_backBuf = 0; + size_t width, height; + }; + std::unordered_map m_windows; }; #elif _WIN32_WINNT_WIN7 @@ -36,6 +47,12 @@ struct D3D11Context { ComPtr m_dev; ComPtr m_devCtx; + struct Window + { + IDXGISwapChain1* m_swapChain; + size_t width, height; + }; + std::unordered_map m_windows; }; #include "boo/System.hpp" diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index 1b9a94d..7a2d33e 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -11,8 +11,8 @@ namespace boo { static LogVisor::LogModule Log("WindowWin32"); class WindowWin32; -IGraphicsCommandQueue* _NewD3D12CommandQueue(D3D12Context* ctx, IGraphicsContext* parent); -IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, IGraphicsContext* parent); +IGraphicsCommandQueue* _NewD3D12CommandQueue(D3D12Context* ctx, D3D12Context::Window* windowCtx, IGraphicsContext* parent); +IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent); struct GraphicsContextWin32 : IGraphicsContext { @@ -47,9 +47,14 @@ public: scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; #if _WIN32_WINNT_WIN10 - IUnknown* dev = d3dCtx.m_ctx12.m_dev ? - static_cast(d3dCtx.m_ctx12.m_dev.Get()) : - static_cast(d3dCtx.m_ctx11.m_dev.Get()); + IUnknown* dev; + if (d3dCtx.m_ctx12.m_dev) + { + scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + dev = static_cast(d3dCtx.m_ctx12.m_dev.Get()); + } + else + dev = static_cast(d3dCtx.m_ctx11.m_dev.Get()); #else IUnknown* dev = static_cast(d3dCtx.m_ctx11.m_dev.Get()); #endif @@ -63,20 +68,45 @@ public: #if _WIN32_WINNT_WIN10 if (d3dCtx.m_ctx12.m_dev) { + auto insIt = d3dCtx.m_ctx12.m_windows.emplace(std::make_pair(parentWindow, D3D12Context::Window())); + D3D12Context::Window& w = insIt.first->second; + m_swapChain.As(&w.m_swapChain); + m_swapChain->GetBuffer(0, __uuidof(ID3D12Resource), &w.m_fb[0]); + m_swapChain->GetBuffer(1, __uuidof(ID3D12Resource), &w.m_fb[1]); + w.m_backBuf = w.m_swapChain->GetCurrentBackBufferIndex(); + D3D12_RESOURCE_DESC resDesc = w.m_fb[0]->GetDesc(); + w.width = resDesc.Width; + w.height = resDesc.Height; m_dataFactory = new D3D12DataFactory(this, &d3dCtx.m_ctx12); - m_commandQueue = _NewD3D12CommandQueue(&d3dCtx.m_ctx12, this); + m_commandQueue = _NewD3D12CommandQueue(&d3dCtx.m_ctx12, &w, this); } else #endif { + auto insIt = d3dCtx.m_ctx11.m_windows.emplace(std::make_pair(parentWindow, D3D11Context::Window())); + D3D11Context::Window& w = insIt.first->second; + ComPtr fbRes; + m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &fbRes); + D3D11_TEXTURE2D_DESC resDesc; + fbRes->GetDesc(&resDesc); + w.width = resDesc.Width; + w.height = resDesc.Height; m_dataFactory = new D3D11DataFactory(this, &d3dCtx.m_ctx11); - m_commandQueue = _NewD3D11CommandQueue(&d3dCtx.m_ctx11, this); + m_commandQueue = _NewD3D11CommandQueue(&d3dCtx.m_ctx11, &insIt.first->second, this); } } ~GraphicsContextWin32() { - +#if _WIN32_WINNT_WIN10 + if (m_d3dCtx.m_ctx12.m_dev) + { + m_d3dCtx.m_ctx12.m_windows.erase(m_parentWindow); + } + else +#endif + { + } } void _setCallback(IWindowCallback* cb)