diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index e3770ba..525d83c 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -89,10 +89,14 @@ class VulkanDataFactory : public IGraphicsDataFactory uint32_t m_drawSamples; static ThreadLocalPtr m_deferredData; std::unordered_set m_committedData; + std::unordered_set m_committedPools; std::mutex m_committedMutex; std::vector m_texUnis; void destroyData(IGraphicsData*); + void destroyPool(IGraphicsBufferPool*); void destroyAllData(); + IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool *pool, BufferUse use, + size_t stride, size_t count); public: VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples); ~VulkanDataFactory() {destroyAllData();} @@ -121,7 +125,8 @@ public: bool enableShaderColorBinding, bool enableShaderDepthBinding); bool bindingNeedsVertexFormat() const {return false;} - IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); + IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, + size_t baseVert = 0, size_t baseInst = 0); IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, std::vector& vertBlobOut, std::vector& fragBlobOut, @@ -146,10 +151,12 @@ public: IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs); + size_t texCount, ITexture** texs, + size_t baseVert = 0, size_t baseInst = 0); }; GraphicsDataToken commitTransaction(const FactoryCommitFunc&); + GraphicsBufferPoolToken newBufferPool(); }; } diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index eb70f85..e19668c 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -59,6 +59,25 @@ struct D3D11Data : IGraphicsData } }; +struct D3D11Pool : IGraphicsBufferPool +{ + size_t m_deleteCountdown = 4; + std::vector> m_DBufs; + + bool decref() + { + if (!m_deleteCountdown) + Log.report(logvisor::Fatal, "Can't decrement 0-data"); + --m_deleteCountdown; + if (!m_deleteCountdown) + { + delete this; + return true; + } + return false; + } +}; + static const D3D11_BIND_FLAG USE_TABLE[] = { D3D11_BIND_VERTEX_BUFFER, @@ -425,13 +444,14 @@ struct D3D11VertexFormat : IVertexFormat { size_t m_elementCount; std::unique_ptr m_elements; + 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]) { memset(m_elements.get(), 0, elementCount * sizeof(D3D11_INPUT_ELEMENT_DESC)); - size_t offset = 0; - size_t instOffset = 0; for (size_t i=0 ; im_dev->CreateVertexShader(vert->GetBufferPointer(), vert->GetBufferSize(), nullptr, &m_vShader)); ThrowIfFailed(ctx->m_dev->CreatePixelShader(pixel->GetBufferPointer(), pixel->GetBufferSize(), nullptr, &m_pShader)); @@ -549,13 +572,14 @@ struct D3D11ShaderDataBinding : IShaderDataBinding std::unique_ptr m_pubufs; size_t m_texCount; std::unique_ptr m_texs; + UINT m_baseOffsets[2]; D3D11ShaderDataBinding(D3D11Context* ctx, IShaderPipeline* pipeline, 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 texCount, ITexture** texs, size_t baseVert, size_t baseInst) : m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), m_instVbuf(instVbuf), @@ -565,6 +589,9 @@ struct D3D11ShaderDataBinding : IShaderDataBinding m_texCount(texCount), m_texs(new ITexture*[texCount]) { + m_baseOffsets[0] = UINT(baseVert * m_pipeline->m_vtxFmt->m_stride); + m_baseOffsets[1] = UINT(baseInst * m_pipeline->m_vtxFmt->m_instStride); + if (ubufStages) { m_pubufs.reset(new bool[ubufCount]); @@ -605,7 +632,6 @@ struct D3D11ShaderDataBinding : IShaderDataBinding ID3D11Buffer* bufs[2] = {}; UINT strides[2] = {}; - UINT offsets[2] = {0,0}; if (m_vbuf) { @@ -639,7 +665,7 @@ struct D3D11ShaderDataBinding : IShaderDataBinding } } - ctx->IASetVertexBuffers(0, 2, bufs, strides, offsets); + ctx->IASetVertexBuffers(0, 2, bufs, strides, m_baseOffsets); if (m_ibuf) { @@ -808,7 +834,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue ComPtr m_cmdLists[3]; D3D11TextureR* m_workDoPresent[3]; - std::mutex m_dynamicLock; + std::recursive_mutex m_dynamicLock; void ProcessDynamicLoads(ID3D11DeviceContext* ctx); static void RenderingWorker(D3D11CommandQueue* self) { @@ -1042,7 +1068,7 @@ void D3D11GraphicsBufferD::update(ID3D11DeviceContext* ctx, int b) } void D3D11GraphicsBufferD::load(const void* data, size_t sz) { - std::unique_lock lk(m_q->m_dynamicLock); + std::unique_lock lk(m_q->m_dynamicLock); size_t bufSz = std::min(sz, m_cpuSz); memcpy(m_cpuBuf.get(), data, bufSz); m_validSlots = 0; @@ -1075,7 +1101,7 @@ void D3D11TextureD::update(ID3D11DeviceContext* ctx, int b) } void D3D11TextureD::load(const void* data, size_t sz) { - std::unique_lock lk(m_q->m_dynamicLock); + std::unique_lock lk(m_q->m_dynamicLock); size_t bufSz = std::min(sz, m_cpuSz); memcpy(m_cpuBuf.get(), data, bufSz); m_validSlots = 0; @@ -1100,8 +1126,10 @@ class D3D11DataFactory : public ID3DDataFactory static thread_local D3D11Data* m_deferredData; struct D3D11Context* m_ctx; std::unordered_set m_committedData; + std::unordered_set m_committedPools; std::mutex m_committedMutex; std::unordered_set m_deletedData; + std::unordered_set m_deletedPools; uint32_t m_sampleCount; void destroyData(IGraphicsData* d) @@ -1117,27 +1145,52 @@ class D3D11DataFactory : public ID3DDataFactory std::unique_lock lk(m_committedMutex); for (IGraphicsData* data : m_committedData) m_deletedData.insert(static_cast(data)); + for (IGraphicsBufferPool* pool : m_committedPools) + m_deletedPools.insert(static_cast(pool)); m_committedData.clear(); + m_committedPools.clear(); + } + + void destroyPool(IGraphicsBufferPool* p) + { + std::unique_lock lk(m_committedMutex); + D3D11Pool* pool = static_cast(p); + m_committedPools.erase(pool); + m_deletedPools.insert(pool); } - std::vector m_toDelete; void procDeletes() { - if (m_deletedData.size()) + for (auto it = m_deletedData.begin(); it != m_deletedData.end();) { - for (IGraphicsData* data : m_deletedData) + D3D11Data* cdata = static_cast(*it); + if (cdata->decref()) { - D3D11Data* cdata = static_cast(data); - if (cdata->decref()) - m_toDelete.push_back(cdata); - } - if (m_toDelete.size()) - { - for (D3D11Data* data : m_toDelete) - m_deletedData.erase(data); - m_toDelete.clear(); + it = m_deletedData.erase(it); + continue; } + ++it; } + for (auto it = m_deletedPools.begin(); it != m_deletedPools.end();) + { + D3D11Pool* cpool = static_cast(*it); + if (cpool->decref()) + { + it = m_deletedPools.erase(it); + continue; + } + ++it; + } + } + + IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, + size_t stride, size_t count) + { + 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_back(retval); + return retval; } public: @@ -1207,7 +1260,8 @@ public: return retval; } - IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) + IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, + size_t baseVert, size_t baseInst) { D3D11CommandQueue* q = static_cast(m_parent.m_parent->getCommandQueue()); D3D11VertexFormat* retval = new struct D3D11VertexFormat(elementCount, elements); @@ -1262,11 +1316,13 @@ public: IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, 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 texCount, ITexture** texs, + size_t baseVert, size_t baseInst) { D3D11ShaderDataBinding* retval = new D3D11ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf, - ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs); + ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, + baseVert, baseInst); static_cast(m_deferredData)->m_SBinds.emplace_back(retval); return retval; } @@ -1293,6 +1349,14 @@ public: lk.unlock(); return GraphicsDataToken(this, retval); } + + GraphicsBufferPoolToken newBufferPool() + { + std::unique_lock lk(m_committedMutex); + D3D11Pool* retval = new D3D11Pool; + m_committedPools.insert(retval); + return GraphicsBufferPoolToken(this, retval); + } }; thread_local D3D11Data* D3D11DataFactory::m_deferredData; @@ -1328,7 +1392,7 @@ void D3D11CommandQueue::execute() void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx) { D3D11DataFactory* gfxF = static_cast(m_parent->getDataFactory()); - std::unique_lock lk(m_dynamicLock); + std::unique_lock lk(m_dynamicLock); std::unique_lock datalk(gfxF->m_committedMutex); for (D3D11Data* d : gfxF->m_committedData) @@ -1338,6 +1402,11 @@ void D3D11CommandQueue::ProcessDynamicLoads(ID3D11DeviceContext* ctx) for (std::unique_ptr& t : d->m_DTexs) t->update(ctx, m_drawBuf); } + for (D3D11Pool* p : gfxF->m_committedPools) + { + for (std::unique_ptr& b : p->m_DBufs) + b->update(ctx, m_drawBuf); + } } IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent) diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 8c20c9e..705ed55 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -55,6 +55,18 @@ struct D3D12Data : IGraphicsData ComPtr m_texHeap; }; +struct D3D12Pool : IGraphicsBufferPool +{ + struct Buffer + { + ComPtr m_bufHeap; + std::unique_ptr m_buf; + Buffer(ComPtr&& heap, class D3D12GraphicsBufferD* buf) + : m_bufHeap(std::move(heap)), m_buf(buf) {} + }; + std::vector m_DBufs; +}; + static const D3D12_RESOURCE_STATES USE_TABLE[] = { D3D12_RESOURCE_STATE_COMMON, @@ -569,13 +581,14 @@ struct D3D12VertexFormat : IVertexFormat { size_t m_elementCount; std::unique_ptr m_elements; + size_t m_stride = 0; + size_t m_instStride = 0; + D3D12VertexFormat(size_t elementCount, const VertexElementDescriptor* elements) : m_elementCount(elementCount), m_elements(new D3D12_INPUT_ELEMENT_DESC[elementCount]) { memset(m_elements.get(), 0, elementCount * sizeof(D3D12_INPUT_ELEMENT_DESC)); - size_t offset = 0; - size_t instOffset = 0; for (size_t i=0 ; im_rs.Get(); @@ -700,22 +716,22 @@ static UINT64 PlaceTextureForGPU(ITexture* tex, D3D12Context* ctx, ID3D12Heap* g } static ID3D12Resource* GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, - D3D12_VERTEX_BUFFER_VIEW& descOut) + D3D12_VERTEX_BUFFER_VIEW& descOut, size_t offset) { if (buf->dynamic()) { const D3D12GraphicsBufferD* cbuf = static_cast(buf); - descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride - offset; descOut.StrideInBytes = cbuf->m_stride; - descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress(); + descOut.BufferLocation = cbuf->m_gpuBufs[idx]->GetGPUVirtualAddress() + offset; return cbuf->m_gpuBufs[idx].Get(); } else { const D3D12GraphicsBufferS* cbuf = static_cast(buf); - descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride; + descOut.SizeInBytes = cbuf->m_count * cbuf->m_stride - offset; descOut.StrideInBytes = cbuf->m_stride; - descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress(); + descOut.BufferLocation = cbuf->m_gpuBuf->GetGPUVirtualAddress() + offset; return cbuf->m_gpuBuf.Get(); } } @@ -909,13 +925,15 @@ struct D3D12ShaderDataBinding : IShaderDataBinding 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; D3D12ShaderDataBinding(D3D12Context* ctx, IShaderPipeline* pipeline, IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf, size_t ubufCount, IGraphicsBuffer** ubufs, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs) + size_t texCount, ITexture** texs, + size_t baseVert, size_t baseInst) : m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), m_instVbuf(instVbuf), @@ -925,6 +943,9 @@ struct D3D12ShaderDataBinding : IShaderDataBinding m_texCount(texCount), m_texs(new ITexture*[texCount]) { + m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride; + m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride; + if (ubufOffs && ubufSizes) { m_ubufOffs.reserve(ubufCount); @@ -967,9 +988,9 @@ struct D3D12ShaderDataBinding : IShaderDataBinding CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_descHeap[b]->GetCPUDescriptorHandleForHeapStart()); if (m_vbuf) - GetBufferGPUResource(m_vbuf, b, m_vboView[b][0]); + GetBufferGPUResource(m_vbuf, b, m_vboView[b][0], m_vertOffset); if (m_instVbuf) - GetBufferGPUResource(m_instVbuf, b, m_vboView[b][1]); + GetBufferGPUResource(m_instVbuf, b, m_vboView[b][1], m_instOffset); if (m_ibuf) GetBufferGPUResource(m_ibuf, b, m_iboView[b]); if (m_ubufOffs.size()) @@ -1511,6 +1532,7 @@ class D3D12DataFactory : public ID3DDataFactory static thread_local D3D12Data* m_deferredData; struct D3D12Context* m_ctx; std::unordered_set m_committedData; + std::unordered_set m_committedPools; std::mutex m_committedMutex; uint32_t m_sampleCount; @@ -1527,8 +1549,47 @@ class D3D12DataFactory : public ID3DDataFactory std::unique_lock lk(m_committedMutex); for (IGraphicsData* data : m_committedData) delete static_cast(data); + for (IGraphicsBufferPool* pool : m_committedPools) + delete static_cast(pool); m_committedData.clear(); + m_committedPools.clear(); } + + void destroyPool(IGraphicsBufferPool* p) + { + std::unique_lock lk(m_committedMutex); + D3D12Pool* pool = static_cast(p); + m_committedPools.erase(pool); + delete pool; + } + + IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, + size_t stride, size_t count) + { + D3D12CommandQueue* q = static_cast(m_parent->getCommandQueue()); + D3D12Pool* pool = static_cast(p); + D3D12GraphicsBufferD* retval = new D3D12GraphicsBufferD(q, use, m_ctx, stride, count); + + /* Gather resource descriptions */ + D3D12_RESOURCE_DESC bufDescs[2]; + bufDescs[0] = retval->m_bufs[0]->GetDesc(); + 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)); + + /* Place resources */ + PlaceBufferForGPU(retval, m_ctx, bufHeap.Get(), 0); + + pool->m_DBufs.emplace_back(std::move(bufHeap), retval); + return retval; + } + public: D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx, uint32_t sampleCount) : m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount) @@ -1614,7 +1675,8 @@ public: return retval; } - IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) + 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); @@ -1673,11 +1735,13 @@ public: 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 texCount, ITexture** texs, + size_t baseVert, size_t baseInst) { D3D12ShaderDataBinding* retval = new D3D12ShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf, - ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs); + ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs, + baseVert, baseInst); static_cast(m_deferredData)->m_SBinds.emplace_back(retval); return retval; } @@ -1800,6 +1864,14 @@ public: lk.unlock(); return GraphicsDataToken(this, retval); } + + GraphicsBufferPoolToken newBufferPool() + { + std::unique_lock lk(m_committedMutex); + D3D12Pool* retval = new D3D12Pool; + m_committedPools.insert(retval); + return GraphicsBufferPoolToken(this, retval); + } }; thread_local D3D12Data* D3D12DataFactory::m_deferredData; @@ -1819,6 +1891,11 @@ void D3D12CommandQueue::execute() for (std::unique_ptr& t : d->m_DTexs) t->update(m_fillBuf); } + for (D3D12Pool* p : gfxF->m_committedPools) + { + for (D3D12Pool::Buffer& b : p->m_DBufs) + b.m_buf->update(m_fillBuf); + } datalk.unlock(); /* Perform dynamic uploads */ diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 4bae2e0..3316902 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -677,6 +677,27 @@ struct VulkanData : IGraphicsData } }; +struct VulkanPool : IGraphicsBufferPool +{ + VulkanContext* m_ctx; + struct Buffer + { + VkDeviceMemory m_bufMem = VK_NULL_HANDLE; + std::unique_ptr m_buffer; + Buffer(VkDeviceMemory mem, class VulkanGraphicsBufferD* buf) + : m_bufMem(mem), m_buffer(buf) {} + }; + std::vector m_DBufs; + bool m_dead = false; + VulkanPool(VulkanContext* ctx) : m_ctx(ctx) {} + ~VulkanPool() + { + for (Buffer& buf : m_DBufs) + if (buf.m_bufMem) + vk::FreeMemory(m_ctx->m_dev, buf.m_bufMem, nullptr); + } +}; + static const VkBufferUsageFlagBits USE_TABLE[] = { VkBufferUsageFlagBits(0), @@ -1631,6 +1652,9 @@ struct VulkanVertexFormat : IVertexFormat VkVertexInputBindingDescription m_bindings[2]; std::unique_ptr m_attributes; VkPipelineVertexInputStateCreateInfo m_info; + size_t m_stride = 0; + size_t m_instStride = 0; + VulkanVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) : m_attributes(new VkVertexInputAttributeDescription[elementCount]) { @@ -1642,8 +1666,6 @@ struct VulkanVertexFormat : IVertexFormat m_info.vertexAttributeDescriptionCount = elementCount; m_info.pVertexAttributeDescriptions = m_attributes.get(); - size_t offset = 0; - size_t instOffset = 0; for (size_t i=0 ; isemantic & boo::VertexSemantic::Instanced) != boo::VertexSemantic::None) { attribute.binding = 1; - attribute.offset = instOffset; - instOffset += SEMANTIC_SIZE_TABLE[semantic]; + attribute.offset = m_instStride; + m_instStride += SEMANTIC_SIZE_TABLE[semantic]; } else { attribute.binding = 0; - attribute.offset = offset; - offset += SEMANTIC_SIZE_TABLE[semantic]; + attribute.offset = m_stride; + m_stride += SEMANTIC_SIZE_TABLE[semantic]; } } - if (offset) + if (m_stride) { m_bindings[0].binding = 0; - m_bindings[0].stride = offset; + m_bindings[0].stride = m_stride; m_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; ++m_info.vertexBindingDescriptionCount; } - if (instOffset) + if (m_instStride) { m_bindings[m_info.vertexBindingDescriptionCount].binding = 1; - m_bindings[m_info.vertexBindingDescriptionCount].stride = instOffset; + m_bindings[m_info.vertexBindingDescriptionCount].stride = m_instStride; m_bindings[m_info.vertexBindingDescriptionCount].inputRate = VK_VERTEX_INPUT_RATE_INSTANCE; ++m_info.vertexBindingDescriptionCount; } @@ -1707,8 +1729,10 @@ static const VkBlendFactor BLEND_FACTOR_TABLE[] = class VulkanShaderPipeline : public IShaderPipeline { friend class VulkanDataFactory; + friend struct VulkanShaderDataBinding; VulkanContext* m_ctx; VkPipelineCache m_pipelineCache; + const VulkanVertexFormat* m_vtxFmt; VulkanShaderPipeline(VulkanContext* ctx, VkShaderModule vert, VkShaderModule frag, @@ -1716,7 +1740,7 @@ class VulkanShaderPipeline : public IShaderPipeline const VulkanVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, bool depthTest, bool depthWrite, bool backfaceCulling) - : m_ctx(ctx), m_pipelineCache(pipelineCache) + : m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt) { VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE] = {}; VkPipelineDynamicStateCreateInfo dynamicState = {}; @@ -1945,6 +1969,9 @@ struct VulkanShaderDataBinding : IShaderDataBinding VkDescriptorPool m_descPool = VK_NULL_HANDLE; VkDescriptorSet m_descSets[2]; + size_t m_vertOffset; + size_t m_instOffset; + #ifndef NDEBUG /* Debugging aids */ bool m_committed = false; @@ -1955,7 +1982,8 @@ struct VulkanShaderDataBinding : IShaderDataBinding IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf, size_t ubufCount, IGraphicsBuffer** ubufs, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs) + size_t texCount, ITexture** texs, + size_t baseVert, size_t baseInst) : m_ctx(ctx), m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), @@ -1966,6 +1994,9 @@ struct VulkanShaderDataBinding : IShaderDataBinding m_texCount(texCount), m_texs(new ITexture*[texCount]) { + m_vertOffset = baseVert * m_pipeline->m_vtxFmt->m_stride; + m_instOffset = baseInst * m_pipeline->m_vtxFmt->m_instStride; + if (ubufOffs && ubufSizes) { m_ubufOffs.reserve(ubufCount); @@ -2027,7 +2058,7 @@ struct VulkanShaderDataBinding : IShaderDataBinding } void commit(VulkanContext* ctx) - { + { VkWriteDescriptorSet writes[(BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT) * 2] = {}; size_t totalWrites = 0; for (int b=0 ; b<2 ; ++b) @@ -2036,13 +2067,13 @@ struct VulkanShaderDataBinding : IShaderDataBinding { const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_vbuf, b); m_vboBufs[b][0] = vbufInfo->buffer; - m_vboOffs[b][0] = vbufInfo->offset; + m_vboOffs[b][0] = vbufInfo->offset + m_vertOffset; } if (m_instVbuf) { const VkDescriptorBufferInfo* vbufInfo = GetBufferGPUResource(m_instVbuf, b); m_vboBufs[b][1] = vbufInfo->buffer; - m_vboOffs[b][1] = vbufInfo->offset; + m_vboOffs[b][1] = vbufInfo->offset + m_instOffset; } if (m_ibuf) { @@ -2769,12 +2800,23 @@ void VulkanDataFactory::destroyData(IGraphicsData* d) data->m_dead = true; } +void VulkanDataFactory::destroyPool(IGraphicsBufferPool* p) +{ + std::unique_lock lk(m_committedMutex); + VulkanPool* pool = static_cast(p); + m_committedPools.erase(pool); + delete pool; +} + void VulkanDataFactory::destroyAllData() { std::unique_lock lk(m_committedMutex); for (IGraphicsData* data : m_committedData) delete static_cast(data); + for (IGraphicsBufferPool* pool : m_committedPools) + delete static_cast(pool); m_committedData.clear(); + m_committedPools.clear(); } VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ctx, uint32_t drawSamples) @@ -3003,7 +3045,9 @@ ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t hei return retval; } -IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) +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(m_deferredData.get())->m_VFmts.emplace_back(retval); @@ -3015,11 +3059,13 @@ IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipe 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 texCount, ITexture** texs, + size_t baseVert, size_t baseInst) { VulkanShaderDataBinding* retval = new VulkanShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf, - ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs); + ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs, + baseVert, baseInst); static_cast(m_deferredData.get())->m_SBinds.emplace_back(retval); return retval; } @@ -3147,6 +3193,46 @@ GraphicsDataToken VulkanDataFactory::commitTransaction return GraphicsDataToken(this, retval); } +IGraphicsBufferD* VulkanDataFactory::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); + + /* 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 = {}; + memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memAlloc.allocationSize = bufMemSize; + ThrowIfFalse(MemoryTypeFromProperties(m_ctx, bufMemTypeBits, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &memAlloc.memoryTypeIndex)); + ThrowIfFailed(vk::AllocateMemory(m_ctx->m_dev, &memAlloc, nullptr, &bufMem)); + + /* place resources */ + retval->placeForGPU(m_ctx, bufMem); + } + + pool->m_DBufs.emplace_back(bufMem, retval); + return retval; +} + +GraphicsBufferPoolToken VulkanDataFactory::newBufferPool() +{ + std::unique_lock lk(m_committedMutex); + VulkanPool* retval = new VulkanPool(m_ctx); + m_committedPools.insert(retval); + return GraphicsBufferPoolToken(this, retval); +} + ThreadLocalPtr VulkanDataFactory::m_deferredData; void VulkanCommandQueue::execute() @@ -3164,6 +3250,11 @@ void VulkanCommandQueue::execute() for (std::unique_ptr& t : d->m_DTexs) t->update(m_fillBuf); } + for (VulkanPool* p : gfxF->m_committedPools) + { + for (VulkanPool::Buffer& b : p->m_DBufs) + b.m_buffer->update(m_fillBuf); + } datalk.unlock(); /* Perform dynamic uploads */ diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index afd35f6..8d4b629 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -5,6 +5,10 @@ #include #include +#if _WIN32_WINNT_WINBLUE +PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor = nullptr; +#endif + #if _DEBUG #define D3D11_CREATE_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG #else @@ -453,6 +457,21 @@ int ApplicationRun(IApplication::EPlatformType platform, platform != IApplication::EPlatformType::Auto) return 1; +#if _WIN32_WINNT_WINBLUE + /* HI-DPI support */ + HMODULE shcoreLib = LoadLibraryW(L"Shcore.dll"); + if (shcoreLib) + { + PFN_SetProcessDpiAwareness MySetProcessDpiAwareness = + (PFN_SetProcessDpiAwareness)GetProcAddress(shcoreLib, "SetProcessDpiAwareness"); + if (MySetProcessDpiAwareness) + MySetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); + + MyGetScaleFactorForMonitor = + (PFN_GetScaleFactorForMonitor)GetProcAddress(shcoreLib, "GetScaleFactorForMonitor"); + } +#endif + WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW); WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE); WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS); diff --git a/lib/win/Win32Common.hpp b/lib/win/Win32Common.hpp index 1f945cd..21ce376 100644 --- a/lib/win/Win32Common.hpp +++ b/lib/win/Win32Common.hpp @@ -16,6 +16,13 @@ extern DWORD g_mainThreadId; namespace boo {class IWindow;} +#if _WIN32_WINNT_WINBLUE +#include +typedef HRESULT (WINAPI* PFN_SetProcessDpiAwareness)( _In_ PROCESS_DPI_AWARENESS ); +typedef HRESULT (WINAPI* PFN_GetScaleFactorForMonitor)( _In_ HMONITOR, _Out_ DEVICE_SCALE_FACTOR *); +extern PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor; +#endif + #if _WIN32_WINNT_WIN10 #include #include diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index 0d316e9..fdc144f 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -1092,7 +1092,18 @@ public: float getVirtualPixelFactor() const { - return 1.0; +#if _WIN32_WINNT_WINBLUE + if (MyGetScaleFactorForMonitor) + { + DEVICE_SCALE_FACTOR Factor; + HMONITOR mon = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY); + MyGetScaleFactorForMonitor(mon, &Factor); + if (Factor == DEVICE_SCALE_FACTOR_INVALID) + return 1.f; + return Factor / 100.f; + } +#endif + return 1.f; } bool isFullscreen() const