From 5f903c09eead505d8af39b8b5c3c1f2550477f97 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 17 Mar 2017 13:31:51 -1000 Subject: [PATCH] Windows sync --- include/boo/graphicsdev/Vulkan.hpp | 9 +- lib/graphicsdev/D3D11.cpp | 219 +++++++++------ lib/graphicsdev/D3D12.cpp | 319 +++++++++++++-------- lib/graphicsdev/Vulkan.cpp | 428 ++++++++++++++++++----------- test/main.cpp | 11 +- 5 files changed, 620 insertions(+), 366 deletions(-) diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index dcc7239..1902cf4 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -122,7 +122,7 @@ public: 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, - bool enableShaderColorBinding, bool enableShaderDepthBinding); + size_t colorBindCount, size_t depthBindCount); bool bindingNeedsVertexFormat() const {return false;} IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, @@ -132,7 +132,8 @@ public: std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling); + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling); IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, @@ -140,7 +141,8 @@ public: bool alphaWrite, CullMode culling) { return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr, - vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling); + vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, + colorWrite, alphaWrite, culling); } IShaderDataBinding* @@ -150,6 +152,7 @@ public: size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* bindIdxs, const bool* bindDepth, size_t baseVert = 0, size_t baseInst = 0); }; }; diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index 19a3b49..b4d5dad 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -47,7 +47,7 @@ static inline void ThrowIfFailed(HRESULT hr) } } -struct D3D11Data : IGraphicsDataPriv +struct D3D11Data : IGraphicsDataPriv { std::vector> m_SPs; std::vector> m_SBinds; @@ -60,10 +60,19 @@ struct D3D11Data : IGraphicsDataPriv std::vector> m_VFmts; }; -class D3D11GraphicsBufferD; +struct D3D11PoolItem : IGraphicsDataPriv +{ + std::unique_ptr m_buf; +}; + struct D3D11Pool : IGraphicsBufferPool { - std::unordered_map> m_DBufs; + std::unordered_set m_items; + ~D3D11Pool() + { + for (auto& item : m_items) + item->decrement(); + } }; static const D3D11_BIND_FLAG USE_TABLE[] = @@ -80,8 +89,9 @@ class D3D11GraphicsBufferS : public IGraphicsBufferS friend struct D3D11CommandQueue; size_t m_sz; - D3D11GraphicsBufferS(BufferUse use, D3D11Context* ctx, const void* data, size_t stride, size_t count) - : m_stride(stride), m_count(count), m_sz(stride * count) + D3D11GraphicsBufferS(IGraphicsData* parent, BufferUse use, D3D11Context* ctx, + const void* data, size_t stride, size_t count) + : IGraphicsBufferS(parent), m_stride(stride), m_count(count), m_sz(stride * count) { D3D11_SUBRESOURCE_DATA iData = {data}; ThrowIfFailed(ctx->m_dev->CreateBuffer(&CD3D11_BUFFER_DESC(m_sz, USE_TABLE[int(use)], D3D11_USAGE_IMMUTABLE), &iData, &m_buf)); @@ -102,8 +112,9 @@ class D3D11GraphicsBufferD : public IGraphicsBufferD std::unique_ptr m_cpuBuf; size_t m_cpuSz; int m_validSlots = 0; - D3D11GraphicsBufferD(D3D11CommandQueue* q, BufferUse use, D3D11Context* ctx, size_t stride, size_t count) - : m_q(q), m_stride(stride), m_count(count) + D3D11GraphicsBufferD(IGraphicsData* parent, D3D11CommandQueue* q, BufferUse use, + D3D11Context* ctx, size_t stride, size_t count) + : IGraphicsBufferD(parent), m_q(q), m_stride(stride), m_count(count) { m_cpuSz = stride * count; m_cpuBuf.reset(new uint8_t[m_cpuSz]); @@ -128,9 +139,9 @@ class D3D11TextureS : public ITextureS friend class D3D11DataFactory; size_t m_sz; - D3D11TextureS(D3D11Context* ctx, size_t width, size_t height, size_t mips, + D3D11TextureS(IGraphicsData* parent, D3D11Context* ctx, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_sz(sz) + : ITextureS(parent), m_sz(sz) { DXGI_FORMAT pfmt; int pxPitchNum = 1; @@ -187,9 +198,9 @@ class D3D11TextureSA : public ITextureSA friend class D3D11DataFactory; size_t m_sz; - D3D11TextureSA(D3D11Context* ctx, size_t width, size_t height, size_t layers, + D3D11TextureSA(IGraphicsData* parent, D3D11Context* ctx, size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_sz(sz) + : ITextureSA(parent), m_sz(sz) { size_t pixelPitch; DXGI_FORMAT pixelFmt; @@ -248,8 +259,9 @@ class D3D11TextureD : public ITextureD size_t m_cpuSz; size_t m_pxPitch; int m_validSlots = 0; - D3D11TextureD(D3D11CommandQueue* q, D3D11Context* ctx, size_t width, size_t height, TextureFormat fmt) - : m_width(width), m_height(height), m_q(q) + D3D11TextureD(IGraphicsData* parent, D3D11CommandQueue* q, D3D11Context* ctx, + size_t width, size_t height, TextureFormat fmt) + : ITextureD(parent), m_width(width), m_height(height), m_q(q) { DXGI_FORMAT pixelFmt; switch (fmt) @@ -289,6 +301,8 @@ public: void unmap(); }; +#define MAX_BIND_TEXS 4 + class D3D11TextureR : public ITextureR { friend class D3D11DataFactory; @@ -297,11 +311,11 @@ class D3D11TextureR : public ITextureR size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; - bool m_enableShaderColorBind; - bool m_enableShaderDepthBind; + size_t m_colorBindCount; + size_t m_depthBindCount; void Setup(D3D11Context* ctx, size_t width, size_t height, size_t samples, - bool enableShaderColorBind, bool enableShaderDepthBind) + size_t colorBindCount, size_t depthBindCount) { ThrowIfFailed(ctx->m_dev->CreateTexture2D(&CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, samples), nullptr, &m_colorTex)); @@ -330,30 +344,35 @@ class D3D11TextureR : public ITextureR ThrowIfFailed(ctx->m_dev->CreateDepthStencilView(m_depthTex.Get(), &CD3D11_DEPTH_STENCIL_VIEW_DESC(m_depthTex.Get(), dsvDim), &m_dsv)); - if (enableShaderColorBind) + for (size_t i=0 ; im_dev->CreateTexture2D(&CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, - 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, samples), nullptr, &m_colorBindTex)); - ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_colorBindTex.Get(), - &CD3D11_SHADER_RESOURCE_VIEW_DESC(m_colorBindTex.Get(), srvDim), &m_colorSrv)); + 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, samples), nullptr, &m_colorBindTex[i])); + ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_colorBindTex[i].Get(), + &CD3D11_SHADER_RESOURCE_VIEW_DESC(m_colorBindTex[i].Get(), srvDim), &m_colorSrv[i])); } - if (enableShaderDepthBind) + for (size_t i=0 ; im_dev->CreateTexture2D(&CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R24G8_TYPELESS, width, height, - 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, samples), nullptr, &m_depthBindTex)); - ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_depthBindTex.Get(), - &CD3D11_SHADER_RESOURCE_VIEW_DESC(m_depthBindTex.Get(), srvDim, DXGI_FORMAT_R24G8_TYPELESS), &m_depthSrv)); + 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, 0, samples), nullptr, &m_depthBindTex[i])); + ThrowIfFailed(ctx->m_dev->CreateShaderResourceView(m_depthBindTex[i].Get(), + &CD3D11_SHADER_RESOURCE_VIEW_DESC(m_depthBindTex[i].Get(), srvDim, DXGI_FORMAT_R24_UNORM_X8_TYPELESS), &m_depthSrv[i])); } } - D3D11TextureR(D3D11Context* ctx, size_t width, size_t height, size_t samples, - bool enableShaderColorBind, bool enableShaderDepthBind) - : m_width(width), m_height(height), m_samples(samples), - m_enableShaderColorBind(enableShaderColorBind), m_enableShaderDepthBind(enableShaderDepthBind) + D3D11TextureR(IGraphicsData* parent, D3D11Context* ctx, size_t width, size_t height, size_t samples, + size_t colorBindCount, size_t depthBindCount) + : ITextureR(parent), m_width(width), m_height(height), m_samples(samples), + m_colorBindCount(colorBindCount), m_depthBindCount(depthBindCount) { + if (colorBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many color bindings for render texture"); + if (depthBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many depth bindings for render texture"); + if (samples == 0) m_samples = 1; - Setup(ctx, width, height, samples, enableShaderColorBind, enableShaderDepthBind); + Setup(ctx, width, height, samples, colorBindCount, depthBindCount); } public: size_t samples() const {return m_samples;} @@ -363,11 +382,11 @@ public: ComPtr m_depthTex; ComPtr m_dsv; - ComPtr m_colorBindTex; - ComPtr m_colorSrv; + ComPtr m_colorBindTex[MAX_BIND_TEXS]; + ComPtr m_colorSrv[MAX_BIND_TEXS]; - ComPtr m_depthBindTex; - ComPtr m_depthSrv; + ComPtr m_depthBindTex[MAX_BIND_TEXS]; + ComPtr m_depthSrv[MAX_BIND_TEXS]; ~D3D11TextureR() = default; @@ -379,7 +398,7 @@ public: height = 1; m_width = width; m_height = height; - Setup(ctx, width, height, m_samples, m_enableShaderColorBind, m_enableShaderDepthBind); + Setup(ctx, width, height, m_samples, m_colorBindCount, m_depthBindCount); } }; @@ -435,9 +454,9 @@ struct D3D11VertexFormat : IVertexFormat size_t m_stride = 0; size_t m_instStride = 0; - D3D11VertexFormat(size_t elementCount, const VertexElementDescriptor* elements) - : m_elementCount(elementCount), - m_elements(new D3D11_INPUT_ELEMENT_DESC[elementCount]) + D3D11VertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements) + : IVertexFormat(parent), m_elementCount(elementCount), + m_elements(new D3D11_INPUT_ELEMENT_DESC[elementCount]) { memset(m_elements.get(), 0, elementCount * sizeof(D3D11_INPUT_ELEMENT_DESC)); for (size_t i=0 ; i(&m_vShader); @@ -529,9 +550,24 @@ class D3D11ShaderPipeline : public IShaderPipeline ThrowIfFailed(ctx->m_dev->CreateRasterizerState(&rasDesc, &m_rasState)); CD3D11_DEPTH_STENCIL_DESC dsDesc(D3D11_DEFAULT); - dsDesc.DepthEnable = depthTest; + dsDesc.DepthEnable = depthTest != ZTest::None; dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK(depthWrite); - dsDesc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL; + switch (depthTest) + { + case ZTest::None: + default: + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + break; + case ZTest::LEqual: + dsDesc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL; + break; + case ZTest::Greater: + dsDesc.DepthFunc = D3D11_COMPARISON_LESS; + break; + case ZTest::Equal: + dsDesc.DepthFunc = D3D11_COMPARISON_EQUAL; + break; + } ThrowIfFailed(ctx->m_dev->CreateDepthStencilState(&dsDesc, &m_dsState)); CD3D11_BLEND_DESC blDesc(D3D11_DEFAULT); @@ -540,6 +576,11 @@ class D3D11ShaderPipeline : public IShaderPipeline blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)]; blDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + blDesc.RenderTarget[0].RenderTargetWriteMask = + (colorWrite ? (D3D11_COLOR_WRITE_ENABLE_RED | + D3D11_COLOR_WRITE_ENABLE_GREEN | + D3D11_COLOR_WRITE_ENABLE_BLUE) : 0) | + (alphaWrite ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0); ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState)); const auto& vertBuf = m_vert.get().m_vtxBlob; @@ -570,7 +611,7 @@ public: } }; -struct D3D11ShaderDataBinding : IShaderDataBindingPriv +struct D3D11ShaderDataBinding : IShaderDataBindingPriv { D3D11ShaderPipeline* m_pipeline; IGraphicsBuffer* m_vbuf; @@ -580,7 +621,13 @@ struct D3D11ShaderDataBinding : IShaderDataBindingPriv std::unique_ptr m_ubufFirstConsts; std::unique_ptr m_ubufNumConsts; std::unique_ptr m_pubufs; - std::vector m_texs; + struct BoundTex + { + ITexture* tex; + int idx; + bool depth; + }; + std::vector m_texs; UINT m_baseOffsets[2]; D3D11ShaderDataBinding(D3D11Data* d, @@ -589,7 +636,8 @@ struct D3D11ShaderDataBinding : IShaderDataBindingPriv IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf, size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, size_t baseVert, size_t baseInst) + size_t texCount, ITexture** texs, const int* texBindIdx, const bool* depthBind, + size_t baseVert, size_t baseInst) : IShaderDataBindingPriv(d), m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), @@ -632,7 +680,7 @@ struct D3D11ShaderDataBinding : IShaderDataBindingPriv } for (size_t i=0 ; i ID3D11ShaderResourceView* srvs[8] = {}; for (int i=0 ; i<8 && itype()) + switch (m_texs[i].tex->type()) { case TextureType::Dynamic: { - D3D11TextureD* ctex = static_cast(m_texs[i]); + D3D11TextureD* ctex = static_cast(m_texs[i].tex); srvs[i] = ctex->m_srvs[b].Get(); break; } case TextureType::Static: { - D3D11TextureS* ctex = static_cast(m_texs[i]); + D3D11TextureS* ctex = static_cast(m_texs[i].tex); srvs[i] = ctex->m_srv.Get(); break; } case TextureType::StaticArray: { - D3D11TextureSA* ctex = static_cast(m_texs[i]); + D3D11TextureSA* ctex = static_cast(m_texs[i].tex); srvs[i] = ctex->m_srv.Get(); break; } case TextureType::Render: { - D3D11TextureR* ctex = static_cast(m_texs[i]); - srvs[i] = ctex->m_colorSrv.Get(); + D3D11TextureR* ctex = static_cast(m_texs[i].tex); + srvs[i] = m_texs[i].depth ? ctex->m_depthSrv[m_texs[i].idx].Get() : + ctex->m_colorSrv[m_texs[i].idx].Get(); break; } } @@ -844,7 +893,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue struct CommandList { ComPtr list; - std::vector::Token> resTokens; + std::vector resTokens; D3D11TextureR* workDoPresent = nullptr; void reset() @@ -1049,14 +1098,14 @@ struct D3D11CommandQueue : IGraphicsCommandQueue m_deferredCtx->DrawIndexedInstanced(count, instCount, start, 0, 0); } - void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth) + void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, int bindIdx, bool color, bool depth) { const D3D11TextureR* tex = static_cast(texture); - if (color && tex->m_enableShaderColorBind) + if (color && tex->m_colorBindCount) { if (tex->m_samples > 1) { - m_deferredCtx->CopyResource(tex->m_colorBindTex.Get(), tex->m_colorTex.Get()); + m_deferredCtx->CopyResource(tex->m_colorBindTex[bindIdx].Get(), tex->m_colorTex.Get()); } else { @@ -1064,13 +1113,13 @@ struct D3D11CommandQueue : IGraphicsCommandQueue int y = tlOrigin ? intersectRect.location[1] : (tex->m_height - intersectRect.size[1] - intersectRect.location[1]); D3D11_BOX box = {UINT(intersectRect.location[0]), UINT(y), 0, UINT(intersectRect.location[0] + intersectRect.size[0]), UINT(y + intersectRect.size[1]), 1}; - m_deferredCtx->CopySubresourceRegion1(tex->m_colorBindTex.Get(), 0, box.left, box.top, 0, + m_deferredCtx->CopySubresourceRegion1(tex->m_colorBindTex[bindIdx].Get(), 0, box.left, box.top, 0, tex->m_colorTex.Get(), 0, &box, D3D11_COPY_DISCARD); } } - if (depth && tex->m_enableShaderDepthBind) + if (depth && tex->m_depthBindCount) { - m_deferredCtx->CopyResource(tex->m_depthBindTex.Get(), tex->m_depthTex.Get()); + m_deferredCtx->CopyResource(tex->m_depthBindTex[bindIdx].Get(), tex->m_depthTex.Get()); } } @@ -1179,8 +1228,8 @@ class D3D11DataFactory : public ID3DDataFactory std::unique_lock lk(m_committedMutex); for (D3D11Data* data : m_committedData) data->decrement(); - for (IGraphicsBufferPool* pool : m_committedPools) - delete static_cast(pool); + for (D3D11Pool* pool : m_committedPools) + delete pool; m_committedData.clear(); m_committedPools.clear(); } @@ -1198,15 +1247,22 @@ class D3D11DataFactory : public ID3DDataFactory { D3D11CommandQueue* q = static_cast(m_parent->getCommandQueue()); D3D11Pool* pool = static_cast(p); - D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(q, use, m_ctx, stride, count); - pool->m_DBufs.emplace(std::make_pair(retval, retval)); + D3D11PoolItem* item = new D3D11PoolItem; + D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(item, q, use, m_ctx, stride, count); + item->m_buf.reset(retval); + pool->m_items.emplace(item); return retval; } void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) { D3D11Pool* pool = static_cast(p); - pool->m_DBufs.erase(static_cast(buf)); + auto search = pool->m_items.find(static_cast(buf->m_parentData)); + if (search != pool->m_items.end()) + { + (*search)->decrement(); + pool->m_items.erase(search); + } } public: @@ -1230,7 +1286,7 @@ public: IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { D3D11Data* d = static_cast(m_deferredData); - D3D11GraphicsBufferS* retval = new D3D11GraphicsBufferS(use, m_parent.m_ctx, data, stride, count); + D3D11GraphicsBufferS* retval = new D3D11GraphicsBufferS(d, use, m_parent.m_ctx, data, stride, count); d->m_SBufs.emplace_back(retval); return retval; } @@ -1239,7 +1295,7 @@ public: { D3D11Data* d = static_cast(m_deferredData); D3D11CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(q, use, m_parent.m_ctx, stride, count); + D3D11GraphicsBufferD* retval = new D3D11GraphicsBufferD(d, q, use, m_parent.m_ctx, stride, count); d->m_DBufs.emplace_back(retval); return retval; } @@ -1248,7 +1304,7 @@ public: const void* data, size_t sz) { D3D11Data* d = static_cast(m_deferredData); - D3D11TextureS* retval = new D3D11TextureS(m_parent.m_ctx, width, height, mips, fmt, data, sz); + D3D11TextureS* retval = new D3D11TextureS(d, m_parent.m_ctx, width, height, mips, fmt, data, sz); d->m_STexs.emplace_back(retval); return retval; } @@ -1257,7 +1313,7 @@ public: TextureFormat fmt, const void* data, size_t sz) { D3D11Data* d = static_cast(m_deferredData); - D3D11TextureSA* retval = new D3D11TextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); + D3D11TextureSA* retval = new D3D11TextureSA(d, m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); d->m_SATexs.emplace_back(retval); return retval; } @@ -1266,17 +1322,17 @@ public: { D3D11Data* d = static_cast(m_deferredData); D3D11CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D11TextureD* retval = new D3D11TextureD(q, m_parent.m_ctx, width, height, fmt); + D3D11TextureD* retval = new D3D11TextureD(d, q, m_parent.m_ctx, width, height, fmt); d->m_DTexs.emplace_back(retval); return retval; } ITextureR* newRenderTexture(size_t width, size_t height, - bool enableShaderColorBind, bool enableShaderDepthBind) + size_t colorBindCount, size_t depthBindCount) { D3D11Data* d = static_cast(m_deferredData); - D3D11TextureR* retval = new D3D11TextureR(m_parent.m_ctx, width, height, m_parent.m_sampleCount, - enableShaderColorBind, enableShaderDepthBind); + D3D11TextureR* retval = new D3D11TextureR(d, m_parent.m_ctx, width, height, m_parent.m_sampleCount, + colorBindCount, depthBindCount); d->m_RTexs.emplace_back(retval); return retval; } @@ -1285,8 +1341,7 @@ public: size_t baseVert, size_t baseInst) { D3D11Data* d = static_cast(m_deferredData); - D3D11CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D11VertexFormat* retval = new struct D3D11VertexFormat(elementCount, elements); + D3D11VertexFormat* retval = new struct D3D11VertexFormat(d, elementCount, elements); d->m_VFmts.emplace_back(retval); return retval; } @@ -1338,7 +1393,8 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { XXH64_state_t hashState; uint64_t srcHashes[2] = {}; @@ -1438,10 +1494,10 @@ public: } D3D11Data* d = static_cast(m_deferredData); - D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(ctx, + D3D11ShaderPipeline* retval = new D3D11ShaderPipeline(d, ctx, std::move(vertShader), std::move(fragShader), static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, culling); + srcFac, dstFac, prim, depthTest, depthWrite, colorWrite, alphaWrite, culling); d->m_SPs.emplace_back(retval); return retval; } @@ -1452,13 +1508,14 @@ public: size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* texBindIdx, const bool* depthBind, size_t baseVert, size_t baseInst) { D3D11Data* d = static_cast(m_deferredData); D3D11ShaderDataBinding* retval = new D3D11ShaderDataBinding(d, m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf, ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, - baseVert, baseInst); + texBindIdx, depthBind, baseVert, baseInst); d->m_SBinds.emplace_back(retval); return retval; } @@ -1545,8 +1602,8 @@ void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx) } for (D3D11Pool* p : gfxF->m_committedPools) { - for (auto& b : p->m_DBufs) - b.second->update(ctx, m_drawBuf); + for (auto& b : p->m_items) + b->m_buf->update(ctx, m_drawBuf); } } diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 86bcc1d..6506cca 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -50,7 +50,7 @@ static inline UINT64 NextHeapOffset(UINT64 offset, const D3D12_RESOURCE_ALLOCATI return (offset + info.Alignment - 1) & ~(info.Alignment - 1); } -struct D3D12Data : IGraphicsDataPriv +struct D3D12Data : IGraphicsDataPriv { std::vector> m_SPs; std::vector> m_SBinds; @@ -65,16 +65,20 @@ struct D3D12Data : IGraphicsDataPriv ComPtr m_texHeap; }; +struct D3D12PoolItem : IGraphicsDataPriv +{ + ComPtr m_bufHeap; + std::unique_ptr m_buf; +}; + struct D3D12Pool : IGraphicsBufferPool { - struct Buffer + std::unordered_set m_items; + ~D3D12Pool() { - ComPtr m_bufHeap; - std::unique_ptr m_buf; - Buffer(ComPtr&& heap, class D3D12GraphicsBufferD* buf) - : m_bufHeap(std::move(heap)), m_buf(buf) {} - }; - std::unordered_map m_DBufs; + for (auto& item : m_items) + item->decrement(); + } }; static const D3D12_RESOURCE_STATES USE_TABLE[] = @@ -92,8 +96,10 @@ class D3D12GraphicsBufferS : public IGraphicsBufferS D3D12_RESOURCE_STATES m_state; size_t m_sz; D3D12_RESOURCE_DESC m_gpuDesc; - D3D12GraphicsBufferS(BufferUse use, D3D12Context* ctx, const void* data, size_t stride, size_t count) - : m_state(USE_TABLE[int(use)]), m_stride(stride), m_count(count), m_sz(stride * count) + D3D12GraphicsBufferS(IGraphicsData* parent, BufferUse use, D3D12Context* ctx, + const void* data, size_t stride, size_t count) + : IGraphicsBufferS(parent), m_state(USE_TABLE[int(use)]), + m_stride(stride), m_count(count), m_sz(stride * count) { size_t gpuSz = use == BufferUse::Uniform ? ((m_sz + 255) & ~255) : m_sz; m_gpuDesc = CD3DX12_RESOURCE_DESC::Buffer(gpuSz); @@ -140,12 +146,13 @@ class D3D12GraphicsBufferD : public IGraphicsBufferD std::unique_ptr m_cpuBuf; size_t m_cpuSz; int m_validSlots = 0; - D3D12GraphicsBufferD(D3D12CommandQueue* q, BufferUse use, D3D12Context* ctx, size_t stride, size_t count) - : m_state(USE_TABLE[int(use)]), m_q(q), m_stride(stride), m_count(count) + D3D12GraphicsBufferD(IGraphicsData* parent, D3D12CommandQueue* q, BufferUse use, + D3D12Context* ctx, size_t stride, size_t count) + : IGraphicsBufferD(parent), m_state(USE_TABLE[int(use)]), m_q(q), m_stride(stride), m_count(count) { m_cpuSz = stride * count; - m_cpuBuf.reset(new uint8_t[m_cpuSz]); - size_t gpuSz = use == BufferUse::Uniform ? ((m_cpuSz + 255) & ~255) : m_cpuSz; + size_t gpuSz = ((m_cpuSz + 255) & ~255); + m_cpuBuf.reset(new uint8_t[gpuSz]); D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Buffer(gpuSz); size_t reqSz = GetRequiredIntermediateSize(ctx->m_dev.Get(), &desc, 0, 1); desc = CD3DX12_RESOURCE_DESC::Buffer(reqSz); @@ -188,9 +195,9 @@ class D3D12TextureS : public ITextureS TextureFormat m_fmt; size_t m_sz; D3D12_RESOURCE_DESC m_gpuDesc; - D3D12TextureS(D3D12Context* ctx, size_t width, size_t height, size_t mips, + D3D12TextureS(IGraphicsData* parent, D3D12Context* ctx, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_fmt(fmt), m_sz(sz), m_mipCount(mips) + : ITextureS(parent), m_fmt(fmt), m_sz(sz), m_mipCount(mips) { DXGI_FORMAT pfmt; int pxPitchNum = 1; @@ -270,9 +277,10 @@ class D3D12TextureSA : public ITextureSA size_t m_layers; size_t m_sz; D3D12_RESOURCE_DESC m_gpuDesc; - D3D12TextureSA(D3D12Context* ctx, size_t width, size_t height, size_t layers, + D3D12TextureSA(IGraphicsData* parent, D3D12Context* ctx, + size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_fmt(fmt), m_layers(layers), m_sz(sz) + : ITextureSA(parent), m_fmt(fmt), m_layers(layers), m_sz(sz) { size_t pxPitch; DXGI_FORMAT pixelFmt; @@ -354,8 +362,9 @@ class D3D12TextureD : public ITextureD size_t m_rowPitch; size_t m_cpuSz; int m_validSlots = 0; - D3D12TextureD(D3D12CommandQueue* q, D3D12Context* ctx, size_t width, size_t height, TextureFormat fmt) - : m_width(width), m_height(height), m_fmt(fmt), m_q(q) + D3D12TextureD(IGraphicsData* parent, D3D12CommandQueue* q, D3D12Context* ctx, + size_t width, size_t height, TextureFormat fmt) + : ITextureD(parent), m_width(width), m_height(height), m_fmt(fmt), m_q(q) { DXGI_FORMAT pixelFmt; size_t pxPitch; @@ -414,6 +423,7 @@ public: }; static const float BLACK_COLOR[] = {0.0,0.0,0.0,1.0}; +#define MAX_BIND_TEXS 4 class D3D12TextureR : public ITextureR { @@ -422,11 +432,11 @@ class D3D12TextureR : public ITextureR size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; - bool m_enableShaderColorBind; - bool m_enableShaderDepthBind; + size_t m_colorBindCount; + size_t m_depthBindCount; void Setup(D3D12Context* ctx, size_t width, size_t height, size_t samples, - bool enableShaderColorBind, bool enableShaderDepthBind) + size_t colorBindCount, size_t depthBindCount) { D3D12_DESCRIPTOR_HEAP_DESC rtvdesc = {D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1}; ThrowIfFailed(ctx->m_dev->CreateDescriptorHeap(&rtvdesc, __uuidof(ID3D12DescriptorHeap), &m_rtvHeap)); @@ -439,7 +449,6 @@ class D3D12TextureR : public ITextureR CD3DX12_RESOURCE_DESC rtvresdesc; CD3DX12_RESOURCE_DESC dsvresdesc; CD3DX12_RESOURCE_DESC cbindresdesc; - CD3DX12_RESOURCE_DESC dbindresdesc; if (samples > 1) { @@ -447,12 +456,10 @@ class D3D12TextureR : public ITextureR dsvDim = D3D12_DSV_DIMENSION_TEXTURE2DMS; rtvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, samples, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); - dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height, 1, 1, samples, + dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R24G8_TYPELESS, width, height, 1, 1, samples, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); cbindresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, samples, 0, D3D12_RESOURCE_FLAG_NONE, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); - dbindresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height, 1, 1, samples, - 0, D3D12_RESOURCE_FLAG_NONE, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); } else { @@ -460,12 +467,10 @@ class D3D12TextureR : public ITextureR dsvDim = D3D12_DSV_DIMENSION_TEXTURE2D; rtvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); - dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height, 1, 1, 1, + dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R24G8_TYPELESS, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL); cbindresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_NONE); - dbindresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D24_UNORM_S8_UINT, width, height, 1, 1, 1, - 0, D3D12_RESOURCE_FLAG_NONE); } D3D12_CLEAR_VALUE colorClear = {}; @@ -486,29 +491,35 @@ class D3D12TextureR : public ITextureR D3D12_DEPTH_STENCIL_VIEW_DESC dsvvdesc = {DXGI_FORMAT_D24_UNORM_S8_UINT, dsvDim}; ctx->m_dev->CreateDepthStencilView(m_depthTex.Get(), &dsvvdesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); - if (enableShaderColorBind) + for (size_t i=0 ; im_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &cbindresdesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, - __uuidof(ID3D12Resource), &m_colorBindTex)); + __uuidof(ID3D12Resource), &m_colorBindTex[i])); } - if (enableShaderDepthBind) + for (size_t i=0 ; im_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &dbindresdesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, - __uuidof(ID3D12Resource), &m_depthBindTex)); + &dsvresdesc, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, nullptr, + __uuidof(ID3D12Resource), &m_depthBindTex[i])); } } D3D12CommandQueue* m_q; - D3D12TextureR(D3D12Context* ctx, D3D12CommandQueue* q, size_t width, size_t height, size_t samples, - bool enableShaderColorBind, bool enableShaderDepthBind) - : m_q(q), m_width(width), m_height(height), m_samples(samples), - m_enableShaderColorBind(enableShaderColorBind), m_enableShaderDepthBind(enableShaderDepthBind) + D3D12TextureR(IGraphicsData* parent, D3D12Context* ctx, D3D12CommandQueue* q, + size_t width, size_t height, size_t samples, + size_t colorBindCount, size_t depthBindCount) + : ITextureR(parent), m_q(q), m_width(width), m_height(height), m_samples(samples), + m_colorBindCount(colorBindCount), m_depthBindCount(depthBindCount) { + if (colorBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many color bindings for render texture"); + if (depthBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many depth bindings for render texture"); + if (samples == 0) m_samples = 1; - Setup(ctx, width, height, samples, enableShaderColorBind, enableShaderDepthBind); + Setup(ctx, width, height, samples, colorBindCount, depthBindCount); } public: size_t samples() const {return m_samples;} @@ -518,9 +529,9 @@ public: ComPtr m_depthTex; ComPtr m_dsvHeap; - ComPtr m_colorBindTex; + ComPtr m_colorBindTex[MAX_BIND_TEXS]; - ComPtr m_depthBindTex; + ComPtr m_depthBindTex[MAX_BIND_TEXS]; ~D3D12TextureR(); @@ -532,7 +543,7 @@ public: height = 1; m_width = width; m_height = height; - Setup(ctx, width, height, m_samples, m_enableShaderColorBind, m_enableShaderDepthBind); + Setup(ctx, width, height, m_samples, m_colorBindCount, m_depthBindCount); } }; @@ -588,8 +599,8 @@ struct D3D12VertexFormat : IVertexFormat size_t m_stride = 0; size_t m_instStride = 0; - D3D12VertexFormat(size_t elementCount, const VertexElementDescriptor* elements) - : m_elementCount(elementCount), + D3D12VertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements) + : IVertexFormat(parent), m_elementCount(elementCount), m_elements(new D3D12_INPUT_ELEMENT_DESC[elementCount]) { memset(m_elements.get(), 0, elementCount * sizeof(D3D12_INPUT_ELEMENT_DESC)); @@ -649,12 +660,13 @@ class D3D12ShaderPipeline : public IShaderPipeline D3D12ShareableShader::Token m_vert; D3D12ShareableShader::Token m_pixel; - D3D12ShaderPipeline(D3D12Context* ctx, D3D12ShareableShader::Token&& vert, + D3D12ShaderPipeline(IGraphicsData* parent, D3D12Context* ctx, D3D12ShareableShader::Token&& vert, D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline, const D3D12VertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling) - : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) + : IShaderPipeline(parent), m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), m_topology(PRIMITIVE_TABLE[int(prim)]) { D3D12_CULL_MODE cullMode; @@ -687,13 +699,32 @@ class D3D12ShaderPipeline : public IShaderPipeline desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; } + desc.BlendState.RenderTarget[0].RenderTargetWriteMask = + (colorWrite ? (D3D12_COLOR_WRITE_ENABLE_RED | + D3D12_COLOR_WRITE_ENABLE_GREEN | + D3D12_COLOR_WRITE_ENABLE_BLUE) : 0) | + (alphaWrite ? D3D12_COLOR_WRITE_ENABLE_ALPHA : 0); desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); desc.RasterizerState.FrontCounterClockwise = TRUE; desc.RasterizerState.CullMode = cullMode; desc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); - desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; - if (!depthTest) - desc.DepthStencilState.DepthEnable = false; + switch (depthTest) + { + case ZTest::None: + default: + desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + break; + case ZTest::LEqual: + desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL; + break; + case ZTest::Greater: + desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS; + break; + case ZTest::Equal: + desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_EQUAL; + break; + } + desc.DepthStencilState.DepthEnable = depthTest != ZTest::None; if (!depthWrite) desc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; desc.InputLayout.NumElements = vtxFmt->m_elementCount; @@ -813,6 +844,17 @@ static const struct RGBATex2DNoMipViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC } } RGBATex2DNoMipViewDesc; +static const struct RGBATex2DDepthViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC +{ + RGBATex2DDepthViewDesc() + { + Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + Texture2D = {UINT(0), UINT(1), UINT(0), 0.0f}; + } +} RGBATex2DDepthViewDesc; + static const struct RGBATex2DViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC { RGBATex2DViewDesc() @@ -868,7 +910,7 @@ static const struct GreyTex2DArrayViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC } } GreyTex2DArrayViewDesc; -static ID3D12Resource* GetTextureGPUResource(const ITexture* tex, int idx, +static ID3D12Resource* GetTextureGPUResource(const ITexture* tex, int idx, int bindIdx, bool depth, D3D12_SHADER_RESOURCE_VIEW_DESC& descOut) { switch (tex->type()) @@ -927,15 +969,23 @@ static ID3D12Resource* GetTextureGPUResource(const ITexture* tex, int idx, case TextureType::Render: { const D3D12TextureR* ctex = static_cast(tex); - descOut = RGBATex2DNoMipViewDesc; - return ctex->m_colorBindTex.Get(); + if (depth) + { + descOut = RGBATex2DDepthViewDesc; + return ctex->m_depthBindTex[bindIdx].Get(); + } + else + { + descOut = RGBATex2DNoMipViewDesc; + return ctex->m_colorBindTex[bindIdx].Get(); + } } default: break; } return nullptr; } -struct D3D12ShaderDataBinding : IShaderDataBindingPriv +struct D3D12ShaderDataBinding : IShaderDataBindingPriv { D3D12ShaderPipeline* m_pipeline; ComPtr m_gpuHeap; @@ -948,7 +998,13 @@ struct D3D12ShaderDataBinding : IShaderDataBindingPriv std::vector> m_ubufOffs; size_t m_texCount; ID3D12Resource* m_knownViewHandles[2][8] = {}; - std::unique_ptr m_texs; + struct BindTex + { + ITexture* tex; + int idx; + bool depth; + }; + std::unique_ptr m_texs; D3D12_VERTEX_BUFFER_VIEW m_vboView[2][2] = {{},{}}; D3D12_INDEX_BUFFER_VIEW m_iboView[2]; size_t m_vertOffset, m_instOffset; @@ -960,6 +1016,7 @@ struct D3D12ShaderDataBinding : IShaderDataBindingPriv size_t ubufCount, IGraphicsBuffer** ubufs, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* bindIdxs, const bool* bindDepth, size_t baseVert, size_t baseInst) : IShaderDataBindingPriv(d), m_pipeline(static_cast(pipeline)), @@ -969,7 +1026,7 @@ struct D3D12ShaderDataBinding : IShaderDataBindingPriv m_ubufCount(ubufCount), m_ubufs(new IGraphicsBuffer*[ubufCount]), m_texCount(texCount), - m_texs(new ITexture*[texCount]) + m_texs(new BindTex[texCount]) { m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride; m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride; @@ -996,7 +1053,9 @@ struct D3D12ShaderDataBinding : IShaderDataBindingPriv } for (size_t i=0 ; i } for (size_t i=0 ; im_dev->CreateShaderResourceView(res, &srvDesc, handle); } @@ -1071,22 +1130,40 @@ struct D3D12ShaderDataBinding : IShaderDataBindingPriv CD3DX12_CPU_DESCRIPTOR_HANDLE heapStart; for (size_t i=0 ; itype() == TextureType::Render) + if (m_texs[i].tex->type() == TextureType::Render) { - const D3D12TextureR* ctex = static_cast(m_texs[i]); - ID3D12Resource* res = ctex->m_colorBindTex.Get(); - if (res != m_knownViewHandles[b][i]) + const D3D12TextureR* ctex = static_cast(m_texs[i].tex); + if (m_texs[i].depth) { - if (incSz == UINT(-1)) + ID3D12Resource* res = ctex->m_depthBindTex[m_texs[i].idx].Get(); + if (res != m_knownViewHandles[b][i]) { - incSz = ctx->m_dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - heapStart = m_descHeap[b]->GetCPUDescriptorHandleForHeapStart(); + if (incSz == UINT(-1)) + { + incSz = ctx->m_dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + heapStart = m_descHeap[b]->GetCPUDescriptorHandleForHeapStart(); + } + m_knownViewHandles[b][i] = res; + ctx->m_dev->CreateShaderResourceView(res, &RGBATex2DDepthViewDesc, + CD3DX12_CPU_DESCRIPTOR_HANDLE(heapStart, MAX_UNIFORM_COUNT + i, incSz)); + } + } + else + { + ID3D12Resource* res = ctex->m_colorBindTex[m_texs[i].idx].Get(); + if (res != m_knownViewHandles[b][i]) + { + if (incSz == UINT(-1)) + { + incSz = ctx->m_dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + heapStart = m_descHeap[b]->GetCPUDescriptorHandleForHeapStart(); + } + m_knownViewHandles[b][i] = res; + ctx->m_dev->CreateShaderResourceView(res, &RGBATex2DNoMipViewDesc, + CD3DX12_CPU_DESCRIPTOR_HANDLE(heapStart, MAX_UNIFORM_COUNT + i, incSz)); } - m_knownViewHandles[b][i] = res; - ctx->m_dev->CreateShaderResourceView(res, &RGBATex2DNoMipViewDesc, - CD3DX12_CPU_DESCRIPTOR_HANDLE(heapStart, MAX_UNIFORM_COUNT + i, incSz)); } } } @@ -1306,23 +1383,25 @@ struct D3D12CommandQueue : IGraphicsCommandQueue m_cmdList->DrawIndexedInstanced(count, instCount, start, 0, 0); } - void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth) + void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, + int bindIdx, bool color, bool depth) { const D3D12TextureR* tex = static_cast(texture); - if (color && tex->m_enableShaderColorBind) + + if (color && tex->m_colorBindCount) { D3D12_RESOURCE_BARRIER copySetup[] = { CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorTex.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorBindTex.Get(), + CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorBindTex[bindIdx].Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST) }; m_cmdList->ResourceBarrier(2, copySetup); if (tex->m_samples > 1) { - m_cmdList->CopyResource(tex->m_colorBindTex.Get(), tex->m_colorTex.Get()); + m_cmdList->CopyResource(tex->m_colorBindTex[bindIdx].Get(), tex->m_colorTex.Get()); } else { @@ -1330,7 +1409,8 @@ struct D3D12CommandQueue : IGraphicsCommandQueue int y = tlOrigin ? intersectRect.location[1] : (tex->m_height - intersectRect.size[1] - intersectRect.location[1]); D3D12_BOX box = {UINT(intersectRect.location[0]), UINT(y), 0, UINT(intersectRect.location[0] + intersectRect.size[0]), UINT(y + intersectRect.size[1]), 1}; - D3D12_TEXTURE_COPY_LOCATION dst = {tex->m_colorBindTex.Get(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX}; + + D3D12_TEXTURE_COPY_LOCATION dst = {tex->m_colorBindTex[bindIdx].Get(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX}; dst.SubresourceIndex = 0; D3D12_TEXTURE_COPY_LOCATION src = {tex->m_colorTex.Get(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX}; src.SubresourceIndex = 0; @@ -1341,29 +1421,29 @@ struct D3D12CommandQueue : IGraphicsCommandQueue { CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorTex.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET), - CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorBindTex.Get(), + CD3DX12_RESOURCE_BARRIER::Transition(tex->m_colorBindTex[bindIdx].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) }; m_cmdList->ResourceBarrier(2, copyTeardown); } - if (depth && tex->m_enableShaderDepthBind) + if (depth && tex->m_depthBindCount) { D3D12_RESOURCE_BARRIER copySetup[] = { CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthTex.Get(), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthBindTex.Get(), + CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthBindTex[bindIdx].Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_COPY_DEST) }; m_cmdList->ResourceBarrier(2, copySetup); - m_cmdList->CopyResource(tex->m_depthBindTex.Get(), tex->m_depthTex.Get()); + m_cmdList->CopyResource(tex->m_depthBindTex[bindIdx].Get(), tex->m_depthTex.Get()); D3D12_RESOURCE_BARRIER copyTeardown[] = { CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthTex.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE), - CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthBindTex.Get(), + CD3DX12_RESOURCE_BARRIER::Transition(tex->m_depthBindTex[bindIdx].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) }; m_cmdList->ResourceBarrier(2, copyTeardown); @@ -1598,7 +1678,9 @@ class D3D12DataFactory : public ID3DDataFactory { D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); D3D12Pool* pool = static_cast(p); - D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(q, use, m_ctx, stride, count); + D3D12PoolItem* item = new D3D12PoolItem; + D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(item, q, use, m_ctx, stride, count); + item->m_buf.reset(retval); /* Gather resource descriptions */ D3D12_RESOURCE_DESC bufDescs[2]; @@ -1606,24 +1688,28 @@ class D3D12DataFactory : public ID3DDataFactory bufDescs[1] = retval->m_bufs[1]->GetDesc(); /* Create heap */ - ComPtr bufHeap; D3D12_RESOURCE_ALLOCATION_INFO bufAllocInfo = m_ctx->m_dev->GetResourceAllocationInfo(0, 2, bufDescs); ThrowIfFailed(m_ctx->m_dev->CreateHeap(&CD3DX12_HEAP_DESC(bufAllocInfo, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS), - __uuidof(ID3D12Heap), &bufHeap)); + __uuidof(ID3D12Heap), &item->m_bufHeap)); /* Place resources */ - PlaceBufferForGPU(retval, m_ctx, bufHeap.Get(), 0); + PlaceBufferForGPU(retval, m_ctx, item->m_bufHeap.Get(), 0); - pool->m_DBufs.emplace(std::make_pair(retval, D3D12Pool::Buffer{std::move(bufHeap), retval})); + pool->m_items.emplace(item); return retval; } void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) { D3D12Pool* pool = static_cast(p); - pool->m_DBufs.erase(static_cast(buf)); + auto search = pool->m_items.find(static_cast(buf->m_parentData)); + if (search != pool->m_items.end()) + { + (*search)->decrement(); + pool->m_items.erase(search); + } } public: @@ -1664,58 +1750,65 @@ public: IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { - D3D12GraphicsBufferS* retval = new D3D12GraphicsBufferS(use, m_parent.m_ctx, data, stride, count); - static_cast(m_deferredData)->m_SBufs.emplace_back(retval); + D3D12Data* d = D3D12DataFactory::m_deferredData; + D3D12GraphicsBufferS* retval = new D3D12GraphicsBufferS(d, use, m_parent.m_ctx, data, stride, count); + d->m_SBufs.emplace_back(retval); return retval; } IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count) { + D3D12Data* d = D3D12DataFactory::m_deferredData; D3D12CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(q, use, m_parent.m_ctx, stride, count); - static_cast(m_deferredData)->m_DBufs.emplace_back(retval); + D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(d, q, use, m_parent.m_ctx, stride, count); + d->m_DBufs.emplace_back(retval); return retval; } ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) { - D3D12TextureS* retval = new D3D12TextureS(m_parent.m_ctx, width, height, mips, fmt, data, sz); - static_cast(m_deferredData)->m_STexs.emplace_back(retval); + D3D12Data* d = D3D12DataFactory::m_deferredData; + D3D12TextureS* retval = new D3D12TextureS(d, m_parent.m_ctx, width, height, mips, fmt, data, sz); + d->m_STexs.emplace_back(retval); return retval; } ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { - D3D12TextureSA* retval = new D3D12TextureSA(m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); - static_cast(m_deferredData)->m_SATexs.emplace_back(retval); + D3D12Data* d = D3D12DataFactory::m_deferredData; + D3D12TextureSA* retval = new D3D12TextureSA(d, m_parent.m_ctx, width, height, layers, mips, fmt, data, sz); + d->m_SATexs.emplace_back(retval); return retval; } ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { + D3D12Data* d = D3D12DataFactory::m_deferredData; D3D12CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D12TextureD* retval = new D3D12TextureD(q, m_parent.m_ctx, width, height, fmt); - static_cast(m_deferredData)->m_DTexs.emplace_back(retval); + D3D12TextureD* retval = new D3D12TextureD(d, q, m_parent.m_ctx, width, height, fmt); + d->m_DTexs.emplace_back(retval); return retval; } ITextureR* newRenderTexture(size_t width, size_t height, - bool enableShaderColorBind, bool enableShaderDepthBind) + size_t colorBindCount, size_t depthBindCount) { + D3D12Data* d = D3D12DataFactory::m_deferredData; D3D12CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); - D3D12TextureR* retval = new D3D12TextureR(m_parent.m_ctx, q, width, height, m_parent.m_sampleCount, - enableShaderColorBind, enableShaderDepthBind); - static_cast(m_deferredData)->m_RTexs.emplace_back(retval); + D3D12TextureR* retval = new D3D12TextureR(d, m_parent.m_ctx, q, width, height, m_parent.m_sampleCount, + colorBindCount, depthBindCount); + d->m_RTexs.emplace_back(retval); return retval; } IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) { - D3D12VertexFormat* retval = new struct D3D12VertexFormat(elementCount, elements); - static_cast(m_deferredData)->m_VFmts.emplace_back(retval); + D3D12Data* d = D3D12DataFactory::m_deferredData; + D3D12VertexFormat* retval = new struct D3D12VertexFormat(d, elementCount, elements); + d->m_VFmts.emplace_back(retval); return retval; } @@ -1768,8 +1861,10 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { + D3D12Data* d = D3D12DataFactory::m_deferredData; XXH64_state_t hashState; uint64_t srcHashes[2] = {}; uint64_t binHashes[2] = {}; @@ -1846,18 +1941,19 @@ public: auto it = m_parent.m_sharedShaders.emplace(std::make_pair(binHashes[1], - std::make_unique(m_parent, srcHashes[0], binHashes[1], + std::make_unique(m_parent, srcHashes[1], binHashes[1], std::move(fragBlob)))).first; fragShader = it->second->lock(); } ID3DBlob* pipeline = pipelineBlob ? pipelineBlob->Get() : nullptr; - D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(m_parent.m_ctx, std::move(vertShader), std::move(fragShader), + D3D12ShaderPipeline* retval = new D3D12ShaderPipeline(d, m_parent.m_ctx, std::move(vertShader), std::move(fragShader), pipeline, static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, culling); + srcFac, dstFac, prim, depthTest, depthWrite, colorWrite, + alphaWrite, culling); if (pipelineBlob && !*pipelineBlob) retval->m_state->GetCachedBlob(&*pipelineBlob); - static_cast(m_deferredData)->m_SPs.emplace_back(retval); + d->m_SPs.emplace_back(retval); return retval; } @@ -1867,13 +1963,14 @@ public: size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* bindIdxs, const bool* bindDepth, size_t baseVert, size_t baseInst) { D3D12Data* d = static_cast(m_deferredData); D3D12ShaderDataBinding* retval = new D3D12ShaderDataBinding(d, m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf, ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs, - baseVert, baseInst); + bindIdxs, bindDepth, baseVert, baseInst); d->m_SBinds.emplace_back(retval); return retval; } @@ -2032,8 +2129,8 @@ void D3D12CommandQueue::execute() } for (D3D12Pool* p : gfxF->m_committedPools) { - for (auto& b : p->m_DBufs) - b.second.m_buf->update(m_fillBuf); + for (auto& b : p->m_items) + b->m_buf->update(m_fillBuf); } datalk.unlock(); diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 2f80269..d0b8449 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -150,27 +150,37 @@ static void SetImageLayout(VkCommandBuffer cmd, VkImage image, imageMemoryBarrier.subresourceRange.baseMipLevel = 0; imageMemoryBarrier.subresourceRange.levelCount = mipCount; imageMemoryBarrier.subresourceRange.layerCount = layerCount; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + + VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; switch (old_image_layout) { case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + src_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: imageMemoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + src_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_PREINITIALIZED: imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + src_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + src_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + src_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; default: break; } @@ -179,30 +189,33 @@ static void SetImageLayout(VkCommandBuffer cmd, VkImage image, { case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + dest_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dest_stages = VK_PIPELINE_STAGE_TRANSFER_BIT; break; case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dest_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + dest_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: imageMemoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + dest_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: imageMemoryBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dest_stages = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; break; default: break; } - VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - vk::CmdPipelineBarrier(cmd, src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, &imageMemoryBarrier); } @@ -325,7 +338,6 @@ void VulkanContext::initVulkan(const char* appName) #ifndef NDEBUG m_layerNames.push_back("VK_LAYER_LUNARG_core_validation"); m_layerNames.push_back("VK_LAYER_LUNARG_object_tracker"); - m_layerNames.push_back("VK_LAYER_LUNARG_image"); m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation"); m_layerNames.push_back("VK_LAYER_LUNARG_swapchain"); m_layerNames.push_back("VK_LAYER_GOOGLE_threading"); @@ -720,7 +732,7 @@ bool VulkanContext::_resizeSwapChains() return true; } -struct VulkanData : IGraphicsDataPriv +struct VulkanData : IGraphicsDataPriv { VulkanContext* m_ctx; VkDeviceMemory m_bufMem = VK_NULL_HANDLE; @@ -745,36 +757,38 @@ struct VulkanData : IGraphicsDataPriv } }; -struct VulkanPool : IGraphicsBufferPool +struct VulkanPoolItem : IGraphicsDataPriv { VulkanContext* m_ctx; - struct Buffer - { - VkDeviceMemory m_bufMem = VK_NULL_HANDLE; - std::unique_ptr m_buffer; - bool m_dead = false; - Buffer(VkDeviceMemory mem, class VulkanGraphicsBufferD* buf) - : m_bufMem(mem), m_buffer(buf) {} - }; - std::unordered_map m_DBufs; + VkDeviceMemory m_bufMem = VK_NULL_HANDLE; + std::unique_ptr m_buf; + bool m_dead = false; + VulkanPoolItem(VulkanContext* ctx) : m_ctx(ctx) {} + ~VulkanPoolItem() + { + if (m_bufMem) + vk::FreeMemory(m_ctx->m_dev, m_bufMem, nullptr); + } +}; + +struct VulkanPool : IGraphicsBufferPool +{ + std::unordered_set m_items; bool m_dead = false; - VulkanPool(VulkanContext* ctx) : m_ctx(ctx) {} ~VulkanPool() { - for (auto& buf : m_DBufs) - if (buf.second.m_bufMem) - vk::FreeMemory(m_ctx->m_dev, buf.second.m_bufMem, nullptr); + for (auto& item : m_items) + item->decrement(); } void clearDeadBuffers() { - for (auto it = m_DBufs.begin() ; it != m_DBufs.end() ;) + for (auto it = m_items.begin() ; it != m_items.end() ;) { - if (it->second.m_dead) + if ((*it)->m_dead) { - if (it->second.m_bufMem) - vk::FreeMemory(m_ctx->m_dev, it->second.m_bufMem, nullptr); - it = m_DBufs.erase(it); + (*it)->decrement(); + it = m_items.erase(it); continue; } ++it; @@ -797,8 +811,9 @@ class VulkanGraphicsBufferS : public IGraphicsBufferS VulkanContext* m_ctx; size_t m_sz; std::unique_ptr m_stagingBuf; - VulkanGraphicsBufferS(BufferUse use, VulkanContext* ctx, const void* data, size_t stride, size_t count) - : m_ctx(ctx), m_stride(stride), m_count(count), m_sz(stride * count), + VulkanGraphicsBufferS(IGraphicsData* parent, BufferUse use, VulkanContext* ctx, + const void* data, size_t stride, size_t count) + : IGraphicsBufferS(parent), m_ctx(ctx), m_stride(stride), m_count(count), m_sz(stride * count), m_stagingBuf(new uint8_t[m_sz]), m_uniform(use == BufferUse::Uniform) { memmove(m_stagingBuf.get(), data, m_sz); @@ -865,8 +880,10 @@ class VulkanGraphicsBufferD : public IGraphicsBufferD size_t m_cpuSz; std::unique_ptr m_cpuBuf; int m_validSlots = 0; - VulkanGraphicsBufferD(VulkanCommandQueue* q, BufferUse use, VulkanContext* ctx, size_t stride, size_t count) - : m_q(q), m_stride(stride), m_count(count), m_cpuSz(stride * count), m_cpuBuf(new uint8_t[m_cpuSz]), + VulkanGraphicsBufferD(IGraphicsData* parent, VulkanCommandQueue* q, BufferUse use, + VulkanContext* ctx, size_t stride, size_t count) + : IGraphicsBufferD(parent), m_q(q), m_stride(stride), m_count(count), + m_cpuSz(stride * count), m_cpuBuf(new uint8_t[m_cpuSz]), m_uniform(use == BufferUse::Uniform) { VkBufferCreateInfo bufInfo = {}; @@ -941,9 +958,10 @@ class VulkanTextureS : public ITextureS int m_pixelPitchNum = 1; int m_pixelPitchDenom = 1; - VulkanTextureS(VulkanContext* ctx, size_t width, size_t height, size_t mips, + VulkanTextureS(IGraphicsData* parent, VulkanContext* ctx, + size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_ctx(ctx), m_fmt(fmt), m_sz(sz), m_width(width), m_height(height), m_mips(mips) + : ITextureS(parent), m_ctx(ctx), m_fmt(fmt), m_sz(sz), m_width(width), m_height(height), m_mips(mips) { VkFormat pfmt; switch (fmt) @@ -1139,9 +1157,11 @@ class VulkanTextureSA : public ITextureSA int m_pixelPitchNum = 1; int m_pixelPitchDenom = 1; - VulkanTextureSA(VulkanContext* ctx, size_t width, size_t height, size_t layers, + VulkanTextureSA(IGraphicsData* parent, VulkanContext* ctx, + size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : m_ctx(ctx), m_fmt(fmt), m_width(width), m_height(height), m_layers(layers), m_mips(mips), m_sz(sz) + : ITextureSA(parent), m_ctx(ctx), m_fmt(fmt), m_width(width), + m_height(height), m_layers(layers), m_mips(mips), m_sz(sz) { VkFormat pfmt; switch (fmt) @@ -1336,8 +1356,9 @@ class VulkanTextureD : public ITextureD VkDeviceSize m_cpuOffsets[2]; VkFormat m_vkFmt; int m_validSlots = 0; - VulkanTextureD(VulkanCommandQueue* q, VulkanContext* ctx, size_t width, size_t height, TextureFormat fmt) - : m_width(width), m_height(height), m_fmt(fmt), m_q(q) + VulkanTextureD(IGraphicsData* parent, VulkanCommandQueue* q, VulkanContext* ctx, + size_t width, size_t height, TextureFormat fmt) + : ITextureD(parent), m_width(width), m_height(height), m_fmt(fmt), m_q(q) { VkFormat pfmt; switch (fmt) @@ -1488,6 +1509,8 @@ public: TextureFormat format() const {return m_fmt;} }; +#define MAX_BIND_TEXS 4 + class VulkanTextureR : public ITextureR { friend class VulkanDataFactory; @@ -1496,11 +1519,11 @@ class VulkanTextureR : public ITextureR size_t m_height = 0; size_t m_samples = 0; - bool m_enableShaderColorBinding; - bool m_enableShaderDepthBinding; + size_t m_colorBindCount; + size_t m_depthBindCount; void Setup(VulkanContext* ctx, size_t width, size_t height, size_t samples, - bool enableShaderColorBinding, bool enableShaderDepthBinding) + size_t colorBindCount, size_t depthBindCount) { /* no-ops on first call */ doDestroy(); @@ -1529,7 +1552,7 @@ class VulkanTextureR : public ITextureR /* depth target */ texCreateInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - texCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + texCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; ThrowIfFailed(vk::CreateImage(ctx->m_dev, &texCreateInfo, nullptr, &m_depthTex)); /* tally total memory requirements */ @@ -1541,7 +1564,9 @@ class VulkanTextureR : public ITextureR memAlloc.allocationSize = 0; uint32_t memTypeBits = ~0; - VkDeviceSize gpuOffsets[4]; + VkDeviceSize gpuOffsets[2]; + VkDeviceSize colorOffsets[MAX_BIND_TEXS]; + VkDeviceSize depthOffsets[MAX_BIND_TEXS]; vk::GetImageMemoryRequirements(ctx->m_dev, m_colorTex, &memReqs); gpuOffsets[0] = memAlloc.allocationSize; @@ -1555,36 +1580,38 @@ class VulkanTextureR : public ITextureR memAlloc.allocationSize = (memAlloc.allocationSize + memReqs.alignment - 1) & ~(memReqs.alignment - 1); memTypeBits &= memReqs.memoryTypeBits; - if (enableShaderColorBinding) + for (size_t i=0 ; im_displayFormat; texCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - ThrowIfFailed(vk::CreateImage(ctx->m_dev, &texCreateInfo, nullptr, &m_colorBindTex)); + ThrowIfFailed(vk::CreateImage(ctx->m_dev, &texCreateInfo, nullptr, &m_colorBindTex[i])); - vk::GetImageMemoryRequirements(ctx->m_dev, m_colorBindTex, &memReqs); - gpuOffsets[2] = memAlloc.allocationSize; + vk::GetImageMemoryRequirements(ctx->m_dev, m_colorBindTex[i], &memReqs); + colorOffsets[i] = memAlloc.allocationSize; memAlloc.allocationSize += memReqs.size; memAlloc.allocationSize = (memAlloc.allocationSize + memReqs.alignment - 1) & ~(memReqs.alignment - 1); memTypeBits &= memReqs.memoryTypeBits; - m_colorBindDescInfo.sampler = ctx->m_linearSampler; - m_colorBindDescInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + m_colorBindDescInfo[i].sampler = ctx->m_linearSampler; + m_colorBindDescInfo[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } - if (enableShaderDepthBinding) + for (size_t i=0 ; im_dev, &texCreateInfo, nullptr, &m_depthBindTex)); + ThrowIfFailed(vk::CreateImage(ctx->m_dev, &texCreateInfo, nullptr, &m_depthBindTex[i])); - vk::GetImageMemoryRequirements(ctx->m_dev, m_depthBindTex, &memReqs); - gpuOffsets[3] = memAlloc.allocationSize; + vk::GetImageMemoryRequirements(ctx->m_dev, m_depthBindTex[i], &memReqs); + depthOffsets[i] = memAlloc.allocationSize; memAlloc.allocationSize += memReqs.size; memAlloc.allocationSize = (memAlloc.allocationSize + memReqs.alignment - 1) & ~(memReqs.alignment - 1); memTypeBits &= memReqs.memoryTypeBits; - m_depthBindDescInfo.sampler = ctx->m_linearSampler; - m_depthBindDescInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + m_depthBindDescInfo[i].sampler = ctx->m_linearSampler; + m_depthBindDescInfo[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } ThrowIfFalse(MemoryTypeFromProperties(ctx, memTypeBits, 0, &memAlloc.memoryTypeIndex)); @@ -1624,24 +1651,24 @@ class VulkanTextureR : public ITextureR viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_depthView)); - if (enableShaderColorBinding) + for (size_t i=0 ; im_dev, m_colorBindTex, m_gpuMem, gpuOffsets[2])); - viewCreateInfo.image = m_colorBindTex; + ThrowIfFailed(vk::BindImageMemory(ctx->m_dev, m_colorBindTex[i], m_gpuMem, colorOffsets[i])); + viewCreateInfo.image = m_colorBindTex[i]; viewCreateInfo.format = ctx->m_displayFormat; viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_colorBindView)); - m_colorBindDescInfo.imageView = m_colorBindView; + ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_colorBindView[i])); + m_colorBindDescInfo[i].imageView = m_colorBindView[i]; } - if (enableShaderDepthBinding) + for (size_t i=0 ; im_dev, m_depthBindTex, m_gpuMem, gpuOffsets[3])); - viewCreateInfo.image = m_depthBindTex; + ThrowIfFailed(vk::BindImageMemory(ctx->m_dev, m_depthBindTex[i], m_gpuMem, depthOffsets[i])); + viewCreateInfo.image = m_depthBindTex[i]; viewCreateInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_depthBindView)); - m_depthBindDescInfo.imageView = m_depthBindView; + viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_depthBindView[i])); + m_depthBindDescInfo[i].imageView = m_depthBindView[i]; } /* framebuffer */ @@ -1670,14 +1697,20 @@ class VulkanTextureR : public ITextureR } VulkanCommandQueue* m_q; - VulkanTextureR(VulkanContext* ctx, VulkanCommandQueue* q, size_t width, size_t height, size_t samples, - bool enableShaderColorBinding, bool enableShaderDepthBinding) - : m_q(q), m_width(width), m_height(height), m_samples(samples), - m_enableShaderColorBinding(enableShaderColorBinding), - m_enableShaderDepthBinding(enableShaderDepthBinding) + VulkanTextureR(IGraphicsData* parent, VulkanContext* ctx, VulkanCommandQueue* q, + size_t width, size_t height, size_t samples, + size_t colorBindCount, size_t depthBindCount) + : ITextureR(parent), m_q(q), m_width(width), m_height(height), m_samples(samples), + m_colorBindCount(colorBindCount), + m_depthBindCount(depthBindCount) { + if (colorBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many color bindings for render texture"); + if (depthBindCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many depth bindings for render texture"); + if (samples == 0) m_samples = 1; - Setup(ctx, width, height, samples, enableShaderColorBinding, enableShaderDepthBinding); + Setup(ctx, width, height, samples, colorBindCount, depthBindCount); } public: size_t samples() const {return m_samples;} @@ -1689,18 +1722,20 @@ public: VkImage m_depthTex = VK_NULL_HANDLE; VkImageView m_depthView = VK_NULL_HANDLE; - VkImage m_colorBindTex = VK_NULL_HANDLE; - VkImageView m_colorBindView = VK_NULL_HANDLE; - VkDescriptorImageInfo m_colorBindDescInfo = {}; + VkImage m_colorBindTex[MAX_BIND_TEXS] = {}; + VkImageView m_colorBindView[MAX_BIND_TEXS] = {}; + VkDescriptorImageInfo m_colorBindDescInfo[MAX_BIND_TEXS] = {}; - VkImage m_depthBindTex = VK_NULL_HANDLE; - VkImageView m_depthBindView = VK_NULL_HANDLE; - VkDescriptorImageInfo m_depthBindDescInfo = {}; + VkImage m_depthBindTex[MAX_BIND_TEXS] = {}; + VkImageView m_depthBindView[MAX_BIND_TEXS] = {}; + VkDescriptorImageInfo m_depthBindDescInfo[MAX_BIND_TEXS] = {}; VkFramebuffer m_framebuffer = VK_NULL_HANDLE; VkRenderPassBeginInfo m_passBeginInfo = {}; VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout m_colorBindLayout[MAX_BIND_TEXS] = {}; + VkImageLayout m_depthBindLayout[MAX_BIND_TEXS] = {}; void doDestroy(); ~VulkanTextureR(); @@ -1713,7 +1748,7 @@ public: height = 1; m_width = width; m_height = height; - Setup(ctx, width, height, m_samples, m_enableShaderColorBinding, m_enableShaderDepthBinding); + Setup(ctx, width, height, m_samples, m_colorBindCount, m_depthBindCount); } }; @@ -1755,8 +1790,9 @@ struct VulkanVertexFormat : IVertexFormat size_t m_stride = 0; size_t m_instStride = 0; - VulkanVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) - : m_attributes(new VkVertexInputAttributeDescription[elementCount]) + VulkanVertexFormat(IGraphicsData* parent, size_t elementCount, + const VertexElementDescriptor* elements) + : IVertexFormat(parent), m_attributes(new VkVertexInputAttributeDescription[elementCount]) { m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; m_info.pNext = nullptr; @@ -1835,14 +1871,16 @@ class VulkanShaderPipeline : public IShaderPipeline const VulkanVertexFormat* m_vtxFmt; VulkanShareableShader::Token m_vert; VulkanShareableShader::Token m_frag; - VulkanShaderPipeline(VulkanContext* ctx, + VulkanShaderPipeline(IGraphicsData* parent, + VulkanContext* ctx, VulkanShareableShader::Token&& vert, VulkanShareableShader::Token&& frag, VkPipelineCache pipelineCache, const VulkanVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling) - : m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) + : IShaderPipeline(parent), m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_frag(std::move(frag)) { VkCullModeFlagBits cullMode; @@ -1925,12 +1963,28 @@ class VulkanShaderPipeline : public IShaderPipeline depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; depthStencilInfo.pNext = nullptr; depthStencilInfo.flags = 0; - depthStencilInfo.depthTestEnable = depthTest; + depthStencilInfo.depthTestEnable = depthTest != ZTest::None; depthStencilInfo.depthWriteEnable = depthWrite; - depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; depthStencilInfo.front.compareOp = VK_COMPARE_OP_ALWAYS; depthStencilInfo.back.compareOp = VK_COMPARE_OP_ALWAYS; + switch (depthTest) + { + case ZTest::None: + default: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_ALWAYS; + break; + case ZTest::LEqual: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + break; + case ZTest::Greater: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_GREATER; + break; + case ZTest::Equal: + depthStencilInfo.depthCompareOp = VK_COMPARE_OP_EQUAL; + break; + } + VkPipelineColorBlendAttachmentState colorAttachment = {}; colorAttachment.blendEnable = dstFac != BlendFactor::Zero; colorAttachment.srcColorBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; @@ -1939,7 +1993,11 @@ class VulkanShaderPipeline : public IShaderPipeline colorAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; colorAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; colorAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - colorAttachment.colorWriteMask = 0xf; + colorAttachment.colorWriteMask = + (colorWrite ? (VK_COLOR_COMPONENT_R_BIT | + VK_COLOR_COMPONENT_G_BIT | + VK_COLOR_COMPONENT_B_BIT) : 0) | + (alphaWrite ? VK_COLOR_COMPONENT_A_BIT : 0); VkPipelineColorBlendStateCreateInfo colorBlendInfo = {}; colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; @@ -2037,7 +2095,7 @@ static const VkDescriptorBufferInfo* GetBufferGPUResource(const IGraphicsBuffer* } } -static const VkDescriptorImageInfo* GetTextureGPUResource(const ITexture* tex, int idx) +static const VkDescriptorImageInfo* GetTextureGPUResource(const ITexture* tex, int idx, int bindIdx, bool depth) { switch (tex->type()) { @@ -2059,14 +2117,14 @@ static const VkDescriptorImageInfo* GetTextureGPUResource(const ITexture* tex, i case TextureType::Render: { const VulkanTextureR* ctex = static_cast(tex); - return &ctex->m_colorBindDescInfo; + return depth ? &ctex->m_depthBindDescInfo[bindIdx] : &ctex->m_colorBindDescInfo[bindIdx]; } default: break; } return nullptr; } -struct VulkanShaderDataBinding : IShaderDataBindingPriv +struct VulkanShaderDataBinding : IShaderDataBindingPriv { VulkanContext* m_ctx; VulkanShaderPipeline* m_pipeline; @@ -2078,7 +2136,13 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv std::vector> m_ubufOffs; size_t m_texCount; VkImageView m_knownViewHandles[2][8] = {}; - std::unique_ptr m_texs; + struct BindTex + { + ITexture* tex; + int idx; + bool depth; + }; + std::unique_ptr m_texs; VkBuffer m_vboBufs[2][2] = {{},{}}; VkDeviceSize m_vboOffs[2][2] = {{},{}}; @@ -2086,7 +2150,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv VkDeviceSize m_iboOffs[2] = {}; VkDescriptorPool m_descPool = VK_NULL_HANDLE; - VkDescriptorSet m_descSets[2]; + VkDescriptorSet m_descSets[2] = {}; size_t m_vertOffset; size_t m_instOffset; @@ -2103,6 +2167,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv size_t ubufCount, IGraphicsBuffer** ubufs, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* bindIdxs, const bool* depthBinds, size_t baseVert, size_t baseInst) : IShaderDataBindingPriv(d), m_ctx(ctx), @@ -2113,7 +2178,7 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv m_ubufCount(ubufCount), m_ubufs(new IGraphicsBuffer*[ubufCount]), m_texCount(texCount), - m_texs(new ITexture*[texCount]) + m_texs(new BindTex[texCount]) { m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride; m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride; @@ -2141,7 +2206,11 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv m_ubufs[i] = ubufs[i]; } for (size_t i=0 ; i 0) @@ -2252,14 +2321,14 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv for (size_t i=0 ; iimageView; @@ -2290,9 +2359,9 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv size_t totalWrites = 0; for (size_t i=0 ; iimageView != m_knownViewHandles[b][i]) { writes[totalWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -2313,7 +2382,9 @@ struct VulkanShaderDataBinding : IShaderDataBindingPriv vk::UpdateDescriptorSets(m_ctx->m_dev, totalWrites, writes, 0, nullptr); vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->m_pipeline); - vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout, 0, 1, &m_descSets[b], 0, nullptr); + if (m_descSets[b]) + vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout, + 0, 1, &m_descSets[b], 0, nullptr); if (m_vbuf && m_instVbuf) vk::CmdBindVertexBuffers(cmdBuf, 0, 2, m_vboBufs[b], m_vboOffs[b]); @@ -2654,7 +2725,8 @@ struct VulkanCommandQueue : IGraphicsCommandQueue return true; } - void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth) + void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, + int bindIdx, bool color, bool depth) { VkCommandBuffer cmdBuf = m_cmdBufs[m_fillBuf]; VulkanTextureR* ctexture = static_cast(texture); @@ -2677,54 +2749,56 @@ struct VulkanCommandQueue : IGraphicsCommandQueue copyInfo.srcSubresource.baseArrayLayer = 0; copyInfo.srcSubresource.layerCount = 1; - if (color && ctexture->m_enableShaderColorBinding) + if (color && ctexture->m_colorBindCount) { if (ctexture == m_boundTarget) SetImageLayout(cmdBuf, ctexture->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1, 1); - SetImageLayout(cmdBuf, ctexture->m_colorBindTex, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); + SetImageLayout(cmdBuf, ctexture->m_colorBindTex[bindIdx], VK_IMAGE_ASPECT_COLOR_BIT, + ctexture->m_colorBindLayout[bindIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; vk::CmdCopyImage(cmdBuf, ctexture->m_colorTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - ctexture->m_colorBindTex, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + ctexture->m_colorBindTex[bindIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info); if (ctexture == m_boundTarget) SetImageLayout(cmdBuf, ctexture->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, 1); - SetImageLayout(cmdBuf, ctexture->m_colorBindTex, VK_IMAGE_ASPECT_COLOR_BIT, + SetImageLayout(cmdBuf, ctexture->m_colorBindTex[bindIdx], VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1, 1); + ctexture->m_colorBindLayout[bindIdx] = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } - if (depth && ctexture->m_enableShaderDepthBinding) + if (depth && ctexture->m_depthBindCount) { if (ctexture == m_boundTarget) SetImageLayout(cmdBuf, ctexture->m_depthTex, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1, 1); - SetImageLayout(cmdBuf, ctexture->m_depthBindTex, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); + SetImageLayout(cmdBuf, ctexture->m_depthBindTex[bindIdx], VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, + ctexture->m_depthBindLayout[bindIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; vk::CmdCopyImage(cmdBuf, ctexture->m_depthTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - ctexture->m_depthBindTex, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + ctexture->m_depthBindTex[bindIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info); if (ctexture == m_boundTarget) SetImageLayout(cmdBuf, ctexture->m_depthTex, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1, 1); - SetImageLayout(cmdBuf, ctexture->m_depthBindTex, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, + SetImageLayout(cmdBuf, ctexture->m_depthBindTex[bindIdx], VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1, 1); + ctexture->m_depthBindLayout[bindIdx] = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } vk::CmdBeginRenderPass(cmdBuf, &m_boundTarget->m_passBeginInfo, VK_SUBPASS_CONTENTS_INLINE); @@ -2777,26 +2851,30 @@ void VulkanTextureR::doDestroy() vk::DestroyImage(m_q->m_ctx->m_dev, m_depthTex, nullptr); m_depthTex = VK_NULL_HANDLE; } - if (m_colorBindView) - { - vk::DestroyImageView(m_q->m_ctx->m_dev, m_colorBindView, nullptr); - m_colorBindView = VK_NULL_HANDLE; - } - if (m_colorBindTex) - { - vk::DestroyImage(m_q->m_ctx->m_dev, m_colorBindTex, nullptr); - m_colorBindTex = VK_NULL_HANDLE; - } - if (m_depthBindView) - { - vk::DestroyImageView(m_q->m_ctx->m_dev, m_depthBindView, nullptr); - m_depthBindView = VK_NULL_HANDLE; - } - if (m_depthBindTex) - { - vk::DestroyImage(m_q->m_ctx->m_dev, m_depthBindTex, nullptr); - m_depthBindTex = VK_NULL_HANDLE; - } + for (size_t i=0 ; im_ctx->m_dev, m_colorBindView[i], nullptr); + m_colorBindView[i] = VK_NULL_HANDLE; + } + for (size_t i=0 ; im_ctx->m_dev, m_colorBindTex[i], nullptr); + m_colorBindTex[i] = VK_NULL_HANDLE; + } + for (size_t i=0 ; im_ctx->m_dev, m_depthBindView[i], nullptr); + m_depthBindView[i] = VK_NULL_HANDLE; + } + for (size_t i=0 ; im_ctx->m_dev, m_depthBindTex[i], nullptr); + m_depthBindTex[i] = VK_NULL_HANDLE; + } if (m_gpuMem) { vk::FreeMemory(m_q->m_ctx->m_dev, m_gpuMem, nullptr); @@ -2811,14 +2889,18 @@ VulkanTextureR::~VulkanTextureR() vk::DestroyImage(m_q->m_ctx->m_dev, m_colorTex, nullptr); vk::DestroyImageView(m_q->m_ctx->m_dev, m_depthView, nullptr); vk::DestroyImage(m_q->m_ctx->m_dev, m_depthTex, nullptr); - if (m_colorBindView) - vk::DestroyImageView(m_q->m_ctx->m_dev, m_colorBindView, nullptr); - if (m_colorBindTex) - vk::DestroyImage(m_q->m_ctx->m_dev, m_colorBindTex, nullptr); - if (m_depthBindView) - vk::DestroyImageView(m_q->m_ctx->m_dev, m_depthBindView, nullptr); - if (m_depthBindTex) - vk::DestroyImage(m_q->m_ctx->m_dev, m_depthBindTex, nullptr); + for (size_t i=0 ; im_ctx->m_dev, m_colorBindView[i], nullptr); + for (size_t i=0 ; im_ctx->m_dev, m_colorBindTex[i], nullptr); + for (size_t i=0 ; im_ctx->m_dev, m_depthBindView[i], nullptr); + for (size_t i=0 ; im_ctx->m_dev, m_depthBindTex[i], nullptr); vk::FreeMemory(m_q->m_ctx->m_dev, m_gpuMem, nullptr); if (m_q->m_boundTarget == this) m_q->m_boundTarget = nullptr; @@ -3081,8 +3163,10 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); XXH64_state_t hashState; @@ -3208,9 +3292,10 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline ThrowIfFailed(vk::CreatePipelineCache(factory.m_ctx->m_dev, &cacheDataInfo, nullptr, &pipelineCache)); } - VulkanShaderPipeline* retval = new VulkanShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader), + VulkanShaderPipeline* retval = new VulkanShaderPipeline(d, factory.m_ctx, std::move(vertShader), std::move(fragShader), pipelineCache, static_cast(vtxFmt), - srcFac, dstFac, prim, depthTest, depthWrite, culling); + srcFac, dstFac, prim, depthTest, depthWrite, colorWrite, + alphaWrite, culling); if (pipelineBlob && pipelineBlob->empty()) { @@ -3224,62 +3309,68 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline } } - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_SPs.emplace_back(retval); + d->m_SPs.emplace_back(retval); return retval; } IGraphicsBufferS* VulkanDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); - VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(use, factory.m_ctx, data, stride, count); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_SBufs.emplace_back(retval); + VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(d, use, factory.m_ctx, data, stride, count); + d->m_SBufs.emplace_back(retval); return retval; } IGraphicsBufferD* VulkanDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); VulkanCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, factory.m_ctx, stride, count); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_DBufs.emplace_back(retval); + VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(d, q, use, factory.m_ctx, stride, count); + d->m_DBufs.emplace_back(retval); return retval; } ITextureS* VulkanDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); - VulkanTextureS* retval = new VulkanTextureS(factory.m_ctx, width, height, mips, fmt, data, sz); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_STexs.emplace_back(retval); + VulkanTextureS* retval = new VulkanTextureS(d, factory.m_ctx, width, height, mips, fmt, data, sz); + d->m_STexs.emplace_back(retval); return retval; } ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); - VulkanTextureSA* retval = new VulkanTextureSA(factory.m_ctx, width, height, layers, mips, fmt, data, sz); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_SATexs.emplace_back(retval); + VulkanTextureSA* retval = new VulkanTextureSA(d, factory.m_ctx, width, height, layers, mips, fmt, data, sz); + d->m_SATexs.emplace_back(retval); return retval; } ITextureD* VulkanDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); VulkanCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - VulkanTextureD* retval = new VulkanTextureD(q, factory.m_ctx, width, height, fmt); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_DTexs.emplace_back(retval); + VulkanTextureD* retval = new VulkanTextureD(d, q, factory.m_ctx, width, height, fmt); + d->m_DTexs.emplace_back(retval); return retval; } ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t height, - bool enableShaderColorBinding, bool enableShaderDepthBinding) + size_t colorBindCount, size_t depthBindCount) { + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); VulkanDataFactoryImpl& factory = static_cast(m_parent); VulkanCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - VulkanTextureR* retval = new VulkanTextureR(factory.m_ctx, q, width, height, factory.m_drawSamples, - enableShaderColorBinding, enableShaderDepthBinding); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_RTexs.emplace_back(retval); + VulkanTextureR* retval = new VulkanTextureR(d, factory.m_ctx, q, width, height, factory.m_drawSamples, + colorBindCount, depthBindCount); + d->m_RTexs.emplace_back(retval); return retval; } @@ -3287,8 +3378,9 @@ IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) { - VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements); - static_cast(VulkanDataFactoryImpl::m_deferredData.get())->m_VFmts.emplace_back(retval); + VulkanData* d = static_cast(VulkanDataFactoryImpl::m_deferredData.get()); + VulkanVertexFormat* retval = new struct VulkanVertexFormat(d, elementCount, elements); + d->m_VFmts.emplace_back(retval); return retval; } @@ -3298,6 +3390,7 @@ IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipe size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* /*ubufStages*/, const size_t* ubufOffs, const size_t* ubufSizes, size_t texCount, ITexture** texs, + const int* bindIdxs, const bool* bindDepth, size_t baseVert, size_t baseInst) { VulkanDataFactoryImpl& factory = static_cast(m_parent); @@ -3305,7 +3398,7 @@ IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipe VulkanShaderDataBinding* retval = new VulkanShaderDataBinding(d, factory.m_ctx, pipeline, vbuf, instVbuf, ibuf, ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs, - baseVert, baseInst); + bindIdxs, bindDepth, baseVert, baseInst); d->m_SBinds.emplace_back(retval); return retval; } @@ -3436,16 +3529,17 @@ GraphicsDataToken VulkanDataFactoryImpl::commitTransaction IGraphicsBufferD* VulkanDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, size_t stride, size_t count) { - VulkanPool* pool = static_cast(p); VulkanCommandQueue* q = static_cast(m_parent->getCommandQueue()); - VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, m_ctx, stride, count); + VulkanPool* pool = static_cast(p); + VulkanPoolItem* item = new VulkanPoolItem(m_ctx); + VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(item, q, use, m_ctx, stride, count); + item->m_buf.reset(retval); /* size up resources */ uint32_t bufMemTypeBits = ~0; VkDeviceSize bufMemSize = retval->sizeForGPU(m_ctx, bufMemTypeBits, 0); /* allocate memory */ - VkDeviceMemory bufMem = VK_NULL_HANDLE; if (bufMemSize) { VkMemoryAllocateInfo memAlloc = {}; @@ -3455,28 +3549,28 @@ IGraphicsBufferD* VulkanDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, B VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &memAlloc.memoryTypeIndex)); - ThrowIfFailed(vk::AllocateMemory(m_ctx->m_dev, &memAlloc, nullptr, &bufMem)); + ThrowIfFailed(vk::AllocateMemory(m_ctx->m_dev, &memAlloc, nullptr, &item->m_bufMem)); /* place resources */ - retval->placeForGPU(m_ctx, bufMem); + retval->placeForGPU(m_ctx, item->m_bufMem); } - pool->m_DBufs.emplace(std::make_pair(retval, VulkanPool::Buffer{bufMem, retval})); + pool->m_items.emplace(item); return retval; } void VulkanDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) { VulkanPool* pool = static_cast(p); - auto search = pool->m_DBufs.find(static_cast(buf)); - if (search != pool->m_DBufs.end()) - search->second.m_dead = true; + auto search = pool->m_items.find(static_cast(buf->m_parentData)); + if (search != pool->m_items.end()) + (*search)->m_dead = true; } GraphicsBufferPoolToken VulkanDataFactoryImpl::newBufferPool() { std::unique_lock lk(m_committedMutex); - VulkanPool* retval = new VulkanPool(m_ctx); + VulkanPool* retval = new VulkanPool; m_committedPools.insert(retval); return GraphicsBufferPoolToken(this, retval); } @@ -3500,8 +3594,8 @@ void VulkanCommandQueue::execute() } for (VulkanPool* p : gfxF->m_committedPools) { - for (auto& b : p->m_DBufs) - b.second.m_buffer->update(m_fillBuf); + for (auto& b : p->m_items) + b->m_buf->update(m_fillBuf); } datalk.unlock(); diff --git a/test/main.cpp b/test/main.cpp index bd51847..dad408a 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -308,7 +308,8 @@ struct TestApplicationCallback : IApplicationCallback pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr, BlendFactor::One, BlendFactor::Zero, - Primitive::TriStrips, boo::ZTest::LEqual, true, true, false, CullMode::None); + Primitive::TriStrips, boo::ZTest::LEqual, + true, true, false, CullMode::None); } #if BOO_HAS_VULKAN else if (plat == IGraphicsDataFactory::Platform::Vulkan) @@ -340,7 +341,8 @@ struct TestApplicationCallback : IApplicationCallback "}\n"; pipeline = vkF.newShaderPipeline(VS, FS, vfmt, BlendFactor::One, BlendFactor::Zero, - Primitive::TriStrips, true, true, CullMode::None); + Primitive::TriStrips, boo::ZTest::LEqual, + true, true, false, CullMode::None); } #endif #if _WIN32 @@ -370,8 +372,9 @@ struct TestApplicationCallback : IApplicationCallback "}\n"; pipeline = d3dF.newShaderPipeline(VS, PS, nullptr, nullptr, nullptr, vfmt, - BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, - true, true, CullMode::None); + BlendFactor::One, BlendFactor::Zero, + Primitive::TriStrips, boo::ZTest::LEqual, + true, true, false, CullMode::None); } #elif BOO_HAS_METAL else if (plat == IGraphicsDataFactory::Platform::Metal)