diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 7dbf10c..c284321 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -12,6 +12,9 @@ #include #include +#define MAX_UNIFORM_COUNT 8 +#define MAX_TEXTURE_COUNT 8 + extern PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC; namespace boo @@ -314,6 +317,10 @@ public: void resize(D3D12Context* ctx, size_t width, size_t height) { + if (width < 1) + width = 1; + if (height < 1) + height = 1; m_width = width; m_height = height; Setup(ctx, width, height, m_samples); @@ -438,6 +445,12 @@ public: D3D12ShaderPipeline(const D3D12ShaderPipeline&) = delete; }; +#if _DEBUG +#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_DEBUG | D3DCOMPILE_OPTIMIZATION_LEVEL0 +#else +#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + IShaderPipeline* D3D12DataFactory::newShaderPipeline (const char* vertSource, const char* fragSource, ComPtr& vertBlobOut, ComPtr& fragBlobOut, @@ -447,14 +460,14 @@ IShaderPipeline* D3D12DataFactory::newShaderPipeline ComPtr errBlob; if (FAILED(D3DCompile(vertSource, strlen(vertSource), "HECL Vert Source", nullptr, nullptr, "main", - "vs_5_0", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &vertBlobOut, &errBlob))) + "vs_5_0", BOO_D3DCOMPILE_FLAG, 0, &vertBlobOut, &errBlob))) { Log.report(LogVisor::FatalError, "error compiling vert shader: %s", errBlob->GetBufferPointer()); return nullptr; } if (FAILED(D3DCompile(fragSource, strlen(fragSource), "HECL Pixel Source", nullptr, nullptr, "main", - "ps_5_0", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &fragBlobOut, &errBlob))) + "ps_5_0", BOO_D3DCOMPILE_FLAG, 0, &fragBlobOut, &errBlob))) { Log.report(LogVisor::FatalError, "error compiling pixel shader: %s", errBlob->GetBufferPointer()); return nullptr; @@ -485,25 +498,62 @@ static UINT64 PlaceTextureForGPU(ITexture* tex, D3D12Context* ctx, ID3D12Heap* g } static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, - D3D12_SHADER_RESOURCE_VIEW_DESC& descOut) + D3D12_VERTEX_BUFFER_VIEW& descOut) { - descOut.Format = DXGI_FORMAT_UNKNOWN; - descOut.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - descOut.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - descOut.Buffer.FirstElement = 0; - descOut.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE; if (buf->dynamic()) { const D3D12GraphicsBufferD* cbuf = static_cast(buf); - descOut.Buffer.NumElements = cbuf->m_count; - descOut.Buffer.StructureByteStride = cbuf->m_stride; + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.StrideInBytes = cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress(); return cbuf->m_gpuBufs[idx].Get(); } else { const D3D12GraphicsBufferS* cbuf = static_cast(buf); - descOut.Buffer.NumElements = cbuf->m_count; - descOut.Buffer.StructureByteStride = cbuf->m_stride; + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.StrideInBytes = cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress(); + return cbuf->m_gpuBuf.Get(); + } +} + +static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, + D3D12_INDEX_BUFFER_VIEW& descOut) +{ + if (buf->dynamic()) + { + const D3D12GraphicsBufferD* cbuf = static_cast(buf); + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress(); + descOut.Format = DXGI_FORMAT_R32_UINT; + return cbuf->m_gpuBufs[idx].Get(); + } + else + { + const D3D12GraphicsBufferS* cbuf = static_cast(buf); + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress(); + descOut.Format = DXGI_FORMAT_R32_UINT; + return cbuf->m_gpuBuf.Get(); + } +} + +static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, + D3D12_CONSTANT_BUFFER_VIEW_DESC& descOut) +{ + if (buf->dynamic()) + { + const D3D12GraphicsBufferD* cbuf = static_cast(buf); + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress(); + return cbuf->m_gpuBufs[idx].Get(); + } + else + { + const D3D12GraphicsBufferS* cbuf = static_cast(buf); + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress(); return cbuf->m_gpuBuf.Get(); } } @@ -571,7 +621,7 @@ struct D3D12ShaderDataBinding : IShaderDataBinding /* 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; + desc.NumDescriptors = MAX_UNIFORM_COUNT + MAX_TEXTURE_COUNT; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; desc.NodeMask = 0; @@ -580,31 +630,28 @@ struct D3D12ShaderDataBinding : IShaderDataBinding { ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&desc, _uuidof(ID3D12DescriptorHeap), &m_descHeap[b])); CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart()); - D3D12_SHADER_RESOURCE_VIEW_DESC viewDesc; - ID3D12Resource* res = GetBufferGPUResource(m_vbuf, b, viewDesc); - m_vboView[b].BufferLocation = res->GetGPUVirtualAddress(); - m_vboView[b].StrideInBytes = viewDesc.Buffer.StructureByteStride; - m_vboView[b].SizeInBytes = viewDesc.Buffer.NumElements * m_vboView[b].StrideInBytes; - ctx->m_dev->CreateShaderResourceView(res, &viewDesc, handle); - handle.Offset(1, incSz); + D3D12_CONSTANT_BUFFER_VIEW_DESC viewDesc; + + GetBufferGPUResource(m_vbuf, b, m_vboView[b]); if (m_ibuf) + GetBufferGPUResource(m_ibuf, b, m_iboView[b]); + for (size_t i=0 ; iGetGPUVirtualAddress(); - m_iboView[b].SizeInBytes = viewDesc.Buffer.NumElements * viewDesc.Buffer.StructureByteStride; - m_iboView[b].Format = DXGI_FORMAT_R32_UINT; - ctx->m_dev->CreateShaderResourceView(res, &viewDesc, handle); - } - handle.Offset(1, incSz); - for (size_t i=0 ; im_dev->CreateShaderResourceView(GetBufferGPUResource(m_ubufs[i], b, viewDesc), &viewDesc, handle); + if (im_dev->CreateConstantBufferView(&viewDesc, handle); + } handle.Offset(1, incSz); } - for (size_t i=0 ; im_dev->CreateShaderResourceView(GetTextureGPUResource(m_texs[i], b), &Tex2DViewDesc, handle); + if (im_dev->CreateShaderResourceView(GetTextureGPUResource(m_texs[i], b), &Tex2DViewDesc, handle); + } handle.Offset(1, incSz); } } @@ -614,6 +661,7 @@ struct D3D12ShaderDataBinding : IShaderDataBinding { ID3D12DescriptorHeap* heap[] = {m_descHeap[b].Get()}; list->SetDescriptorHeaps(1, heap); + list->SetGraphicsRootDescriptorTable(0, m_descHeap[b]->GetGPUDescriptorHandleForHeapStart()); list->SetPipelineState(m_pipeline->m_state.Get()); list->IASetVertexBuffers(0, 1, &m_vboView[b]); if (m_ibuf) @@ -637,19 +685,21 @@ D3D12DataFactory::newShaderDataBinding(IShaderPipeline* pipeline, D3D12DataFactory::D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx) : m_parent(parent), m_deferredData(new struct D3D12Data()), m_ctx(ctx) { - CD3DX12_DESCRIPTOR_RANGE cbvRange(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 0); - CD3DX12_DESCRIPTOR_RANGE srvRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 8, 0); - CD3DX12_ROOT_PARAMETER rootParms[2]; - rootParms[0].InitAsDescriptorTable(1, &cbvRange, D3D12_SHADER_VISIBILITY_VERTEX); - rootParms[1].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); + CD3DX12_DESCRIPTOR_RANGE ranges[] = + { + {D3D12_DESCRIPTOR_RANGE_TYPE_CBV, MAX_UNIFORM_COUNT, 0}, + {D3D12_DESCRIPTOR_RANGE_TYPE_SRV, MAX_TEXTURE_COUNT, 0} + }; + CD3DX12_ROOT_PARAMETER rootParms[1]; + rootParms[0].InitAsDescriptorTable(2, ranges); ComPtr rsOutBlob; ComPtr rsErrorBlob; ThrowIfFailed(D3D12SerializeRootSignaturePROC( - &CD3DX12_ROOT_SIGNATURE_DESC(2, rootParms, 1, &CD3DX12_STATIC_SAMPLER_DESC(0), + &CD3DX12_ROOT_SIGNATURE_DESC(1, rootParms, 1, &CD3DX12_STATIC_SAMPLER_DESC(0), D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT), D3D_ROOT_SIGNATURE_VERSION_1, &rsOutBlob, &rsErrorBlob)); - + ThrowIfFailed(ctx->m_dev->CreateRootSignature(0, rsOutBlob->GetBufferPointer(), rsOutBlob->GetBufferSize(), __uuidof(ID3D12RootSignature), &ctx->m_rs)); } @@ -735,6 +785,8 @@ IGraphicsData* D3D12DataFactory::commit() ++m_ctx->m_loadfenceval; ThrowIfFailed(m_ctx->m_loadq->Signal(m_ctx->m_loadfence.Get(), m_ctx->m_loadfenceval)); + WaitForLoadList(m_ctx); + /* Commit data bindings (create descriptor heaps) */ for (std::unique_ptr& bind : retval->m_SBinds) bind->commit(m_ctx); @@ -899,7 +951,18 @@ struct D3D12CommandQueue : IGraphicsCommandQueue { D3D12TextureR* csource = static_cast(source); - ID3D12Resource* dest = m_windowCtx->m_fb[m_windowCtx->m_backBuf].Get(); + if (m_windowCtx->m_needsResize) + { + UINT nodeMasks[] = {0,0}; + IUnknown* const queues[] = {m_ctx->m_q.Get(), m_ctx->m_q.Get()}; + m_windowCtx->m_swapChain->ResizeBuffers1(2, m_windowCtx->width, m_windowCtx->height, + DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, nodeMasks, queues); + m_windowCtx->m_backBuf = m_windowCtx->m_swapChain->GetCurrentBackBufferIndex(); + m_windowCtx->m_needsResize = false; + } + + ComPtr dest; + ThrowIfFailed(m_windowCtx->m_swapChain->GetBuffer(m_windowCtx->m_backBuf, __uuidof(ID3D12Resource), &dest)); if (csource->m_samples > 1) { @@ -909,18 +972,18 @@ struct D3D12CommandQueue : IGraphicsCommandQueue { CD3DX12_RESOURCE_BARRIER::Transition(src, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RESOLVE_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(dest, + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), 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); + m_cmdList->ResolveSubresource(dest.Get(), 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, + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT) }; m_cmdList->ResourceBarrier(2, msaaTeardown); @@ -933,18 +996,18 @@ struct D3D12CommandQueue : IGraphicsCommandQueue { CD3DX12_RESOURCE_BARRIER::Transition(src, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(dest, + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) }; m_cmdList->ResourceBarrier(2, copySetup); - m_cmdList->CopyResource(dest, src); + m_cmdList->CopyResource(dest.Get(), 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, + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) }; m_cmdList->ResourceBarrier(2, copyTeardown); diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index cc3a9a5..ed5b87f 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -35,8 +35,8 @@ struct D3D12Context struct Window { ComPtr m_swapChain; - ComPtr m_fb[2]; /* Double-buffered */ UINT m_backBuf = 0; + bool m_needsResize = false; size_t width, height; }; std::unordered_map m_windows; @@ -57,6 +57,7 @@ struct D3D11Context struct Window { IDXGISwapChain1* m_swapChain; + bool m_needsResize = false; size_t width, height; }; std::unordered_map m_windows; @@ -68,6 +69,24 @@ struct D3DAppContext #if _WIN32_WINNT_WIN10 D3D12Context m_ctx12; #endif + + void resize(boo::IWindow* window, size_t width, size_t height) + { +#if _WIN32_WINNT_WIN10 + if (m_ctx12.m_dev) + { + m_ctx12.m_windows[window].width = width; + m_ctx12.m_windows[window].height = height; + m_ctx12.m_windows[window].m_needsResize = true; + } + else +#endif + { + m_ctx11.m_windows[window].width = width; + m_ctx11.m_windows[window].height = height; + m_ctx11.m_windows[window].m_needsResize = true; + } + } }; struct HWNDEvent diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index 211e8b6..6a6713d 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -63,10 +63,10 @@ public: Log.report(LogVisor::FatalError, "unable to create swap chain"); 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]); + ComPtr fb; + m_swapChain->GetBuffer(0, __uuidof(ID3D12Resource), &fb); w.m_backBuf = w.m_swapChain->GetCurrentBackBufferIndex(); - D3D12_RESOURCE_DESC resDesc = w.m_fb[0]->GetDesc(); + D3D12_RESOURCE_DESC resDesc = fb->GetDesc(); w.width = resDesc.Width; w.height = resDesc.Height; } @@ -281,7 +281,7 @@ public: void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const { RECT rct; - GetWindowRect(m_hwnd, &rct); + GetClientRect(m_hwnd, &rct); xOut = rct.left; yOut = rct.top; wOut = rct.right; @@ -291,7 +291,7 @@ public: void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const { RECT rct; - GetWindowRect(m_hwnd, &rct); + GetClientRect(m_hwnd, &rct); xOut = rct.left; yOut = rct.top; wOut = rct.right; @@ -374,17 +374,13 @@ public: { case WM_SIZE: { + SWindowRect rect; + getWindowFrame(rect.location[0], rect.location[1], rect.size[0], rect.size[1]); + if (!rect.size[0] || !rect.size[1]) + return; + m_gfxCtx->m_d3dCtx.resize(this, rect.size[0], rect.size[1]); if (m_callback) - { - SWindowRect rect; - int x, y, w, h; - getWindowFrame(x, y, w, h); - rect.location[0] = x; - rect.location[1] = y; - rect.size[0] = LOWORD(e.lParam); - rect.size[1] = HIWORD(e.lParam); m_callback->resized(rect); - } return; } case WM_KEYDOWN: