From 05c26a535b23b1b787523e896853c3641cb888c8 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 13 Mar 2017 21:02:53 -1000 Subject: [PATCH] OpenGL and metal rendering interface upgrades --- include/boo/graphicsdev/D3D.hpp | 3 +- include/boo/graphicsdev/GL.hpp | 9 +- .../boo/graphicsdev/IGraphicsCommandQueue.hpp | 3 +- .../boo/graphicsdev/IGraphicsDataFactory.hpp | 74 ++-- include/boo/graphicsdev/Metal.hpp | 9 +- include/boo/graphicsdev/Vulkan.hpp | 5 +- lib/graphicsdev/Common.hpp | 33 +- lib/graphicsdev/D3D11.cpp | 8 +- lib/graphicsdev/D3D12.cpp | 9 +- lib/graphicsdev/GL.cpp | 332 ++++++++++------ lib/graphicsdev/Metal.mm | 371 ++++++++++++------ lib/graphicsdev/Vulkan.cpp | 6 +- lib/mac/WindowCocoa.mm | 8 +- test/main.cpp | 7 +- 14 files changed, 592 insertions(+), 285 deletions(-) diff --git a/include/boo/graphicsdev/D3D.hpp b/include/boo/graphicsdev/D3D.hpp index 804cc9e..f5e1555 100644 --- a/include/boo/graphicsdev/D3D.hpp +++ b/include/boo/graphicsdev/D3D.hpp @@ -31,7 +31,8 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling)=0; + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling)=0; }; }; diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index 8a2ef8a..80d7e71 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -30,7 +30,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 colorBindingCount, size_t depthBindingCount); bool bindingNeedsVertexFormat() const {return true;} IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, @@ -40,7 +40,8 @@ public: size_t texCount, const char** texNames, size_t uniformBlockCount, const char** uniformBlockNames, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling); + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling); IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, @@ -48,7 +49,9 @@ 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 baseVert = 0, size_t baseInst = 0); + size_t texCount, ITexture** texs, + const int* texBindIdx, const bool* depthBind, + size_t baseVert = 0, size_t baseInst = 0); }; }; diff --git a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp index 63f6433..df5495b 100644 --- a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp +++ b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp @@ -32,7 +32,8 @@ struct IGraphicsCommandQueue virtual void drawInstances(size_t start, size_t count, size_t instCount)=0; virtual void drawInstancesIndexed(size_t start, size_t count, size_t instCount)=0; - virtual void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth)=0; + virtual void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, + bool tlOrigin, int bindIdx, bool color, bool depth)=0; virtual void resolveDisplay(ITextureR* source)=0; virtual void execute()=0; diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 04d818a..42bddb2 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -11,12 +11,22 @@ namespace boo { struct IGraphicsCommandQueue; +/** Opaque object for maintaining ownership of factory-created resources */ +struct IGraphicsData { virtual ~IGraphicsData() = default; }; +class GraphicsDataToken; + +/** Opaque object for maintaining ownership of factory-created pool buffers */ +struct IGraphicsBufferPool {}; +class GraphicsBufferPoolToken; + struct IGraphicsBuffer { bool dynamic() const {return m_dynamic;} + IGraphicsData* m_parentData; protected: bool m_dynamic; - IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {} + IGraphicsBuffer(IGraphicsData* parent, bool dynamic) + : m_parentData(parent), m_dynamic(dynamic) {} virtual ~IGraphicsBuffer() = default; }; @@ -24,7 +34,7 @@ protected: struct IGraphicsBufferS : IGraphicsBuffer { protected: - IGraphicsBufferS() : IGraphicsBuffer(false) {} + IGraphicsBufferS(IGraphicsData* parent) : IGraphicsBuffer(parent, false) {} }; /** Dynamic resource buffer for verts, indices, uniform constants */ @@ -34,7 +44,7 @@ struct IGraphicsBufferD : IGraphicsBuffer virtual void* map(size_t sz)=0; virtual void unmap()=0; protected: - IGraphicsBufferD() : IGraphicsBuffer(true) {} + IGraphicsBufferD(IGraphicsData* parent) : IGraphicsBuffer(parent, true) {} }; /** Supported buffer uses */ @@ -57,9 +67,11 @@ enum class TextureType struct ITexture { TextureType type() const {return m_type;} + IGraphicsData* m_parentData; protected: TextureType m_type; - ITexture(TextureType type) : m_type(type) {} + ITexture(IGraphicsData* parent, TextureType type) + : m_parentData(parent), m_type(type) {} virtual ~ITexture() {} }; @@ -67,14 +79,14 @@ protected: struct ITextureS : ITexture { protected: - ITextureS() : ITexture(TextureType::Static) {} + ITextureS(IGraphicsData* parent) : ITexture(parent, TextureType::Static) {} }; /** Static-array resource buffer for array textures */ struct ITextureSA : ITexture { protected: - ITextureSA() : ITexture(TextureType::StaticArray) {} + ITextureSA(IGraphicsData* parent) : ITexture(parent, TextureType::StaticArray) {} }; /** Dynamic resource buffer for textures */ @@ -84,14 +96,14 @@ struct ITextureD : ITexture virtual void* map(size_t sz)=0; virtual void unmap()=0; protected: - ITextureD() : ITexture(TextureType::Dynamic) {} + ITextureD(IGraphicsData* parent) : ITexture(parent, TextureType::Dynamic) {} }; /** Resource buffer for render-target textures */ struct ITextureR : ITexture { protected: - ITextureR() : ITexture(TextureType::Render) {} + ITextureR(IGraphicsData* parent) : ITexture(parent, TextureType::Render) {} }; /** Supported texture formats */ @@ -106,7 +118,12 @@ enum class TextureFormat /** Opaque token for representing the data layout of a vertex * in a VBO. Also able to reference buffers for platforms like * OpenGL that cache object refs */ -struct IVertexFormat {}; +struct IVertexFormat +{ + IGraphicsData* m_parentData; +protected: + IVertexFormat(IGraphicsData* parent) : m_parentData(parent) {} +}; /** Types of vertex attributes */ enum class VertexSemantic @@ -141,21 +158,18 @@ struct VertexElementDescriptor /** Opaque token for referencing a complete graphics pipeline state necessary * to rasterize geometry (shaders and blending modes mainly) */ -struct IShaderPipeline {}; +struct IShaderPipeline +{ + IGraphicsData* m_parentData; +protected: + IShaderPipeline(IGraphicsData* parent) : m_parentData(parent) {} +}; /** Opaque token serving as indirection table for shader resources * and IShaderPipeline reference. Each renderable surface-material holds one * as a reference */ struct IShaderDataBinding {}; -/** Opaque object for maintaining ownership of factory-created resources */ -struct IGraphicsData {}; -class GraphicsDataToken; - -/** Opaque object for maintaining ownership of factory-created pool buffers */ -struct IGraphicsBufferPool {}; -class GraphicsBufferPoolToken; - /** Used wherever distinction of pipeline stages is needed */ enum class PipelineStage { @@ -178,6 +192,15 @@ enum class CullMode Frontface }; +/** Used by platform shader pipeline constructors */ +enum class ZTest +{ + None, + LEqual, /* Flipped on Vulkan, D3D, Metal */ + Greater, + Equal +}; + /** Used by platform shader pipeline constructors */ enum class BlendFactor { @@ -234,7 +257,7 @@ struct IGraphicsDataFactory newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; virtual ITextureR* newRenderTexture(size_t width, size_t height, - bool enableShaderColorBinding, bool enableShaderDepthBinding)=0; + size_t colorBindingCount, size_t depthBindingCount)=0; virtual bool bindingNeedsVertexFormat() const=0; virtual IVertexFormat* @@ -247,28 +270,33 @@ struct IGraphicsDataFactory 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 baseVert = 0, size_t baseInst = 0)=0; + size_t texCount, ITexture** texs, + const int* texBindIdx, const bool* depthBind, + size_t baseVert = 0, size_t baseInst = 0)=0; IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, IVertexFormat* vtxFormat, IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, - size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0) + size_t texCount, ITexture** texs, + const int* texBindIdx, const bool* depthBind, + size_t baseVert = 0, size_t baseInst = 0) { return newShaderDataBinding(pipeline, vtxFormat, vbo, instVbo, ibo, ubufCount, ubufs, ubufStages, nullptr, - nullptr, texCount, texs, baseVert, baseInst); + nullptr, texCount, texs, texBindIdx, depthBind, + baseVert, baseInst); } }; virtual GraphicsDataToken commitTransaction(const std::function&)=0; virtual GraphicsBufferPoolToken newBufferPool()=0; + virtual void destroyAllData()=0; private: friend class GraphicsDataToken; virtual void destroyData(IGraphicsData*)=0; - virtual void destroyAllData()=0; friend class GraphicsBufferPoolToken; virtual void destroyPool(IGraphicsBufferPool*)=0; diff --git a/include/boo/graphicsdev/Metal.hpp b/include/boo/graphicsdev/Metal.hpp index 837212b..9b0b5fb 100644 --- a/include/boo/graphicsdev/Metal.hpp +++ b/include/boo/graphicsdev/Metal.hpp @@ -31,7 +31,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, @@ -40,7 +40,8 @@ public: IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, unsigned targetSamples, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling); + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling); IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, @@ -48,7 +49,9 @@ 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 baseVert = 0, size_t baseInst = 0); + size_t texCount, ITexture** texs, + const int* texBindIdxs, const bool* depthBind, + size_t baseVert = 0, size_t baseInst = 0); }; }; diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 2e01fac..dcc7239 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -132,11 +132,12 @@ public: std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling); + ZTest depthTest, bool depthWrite, CullMode culling); IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr, vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling); diff --git a/lib/graphicsdev/Common.hpp b/lib/graphicsdev/Common.hpp index afcabbb..52f8739 100644 --- a/lib/graphicsdev/Common.hpp +++ b/lib/graphicsdev/Common.hpp @@ -5,12 +5,12 @@ * binding lifetimes through rendering cycle */ #include +#include #include "boo/graphicsdev/IGraphicsDataFactory.hpp" namespace boo { -template class IGraphicsDataPriv : public IGraphicsData { std::atomic_int m_refCount = {1}; @@ -19,35 +19,50 @@ public: void decrement() { if (m_refCount.fetch_sub(1) == 1) - delete static_cast(this); + delete this; } }; -template class IShaderDataBindingPriv : public IShaderDataBinding { - IGraphicsDataPriv* m_parent; + IGraphicsDataPriv* m_parent; + std::vector m_depDatas; public: - IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {} + IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {} class Token { - IGraphicsDataPriv* m_data = nullptr; + IGraphicsDataPriv* m_data = nullptr; public: Token() = default; Token(const IShaderDataBindingPriv* p) - : m_data(p->m_parent) - { m_data->increment(); } + : m_data(p->m_parent) { m_data->increment(); } Token& operator=(const Token&) = delete; Token(const Token&) = delete; Token& operator=(Token&& other) { m_data = other.m_data; other.m_data = nullptr; return *this; } Token(Token&& other) { m_data = other.m_data; other.m_data = nullptr; } - ~Token() { if (m_data) m_data->decrement(); } + ~Token() { if (m_data) { m_data->decrement(); } } }; Token lock() const { return Token(this); } + ~IShaderDataBindingPriv() + { + for (IGraphicsDataPriv* dep : m_depDatas) + dep->decrement(); + } + +protected: + void addDepData(IGraphicsData* data) + { + IGraphicsDataPriv* d = static_cast(data); + if (d != m_parent) + { + m_depDatas.push_back(d); + d->increment(); + } + } }; template diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index 3365a03..19a3b49 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -501,7 +501,7 @@ class D3D11ShaderPipeline : public IShaderPipeline D3D11ShareableShader::Token&& pixel, const D3D11VertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), m_topology(PRIMITIVE_TABLE[int(prim)]) { @@ -538,6 +538,8 @@ class D3D11ShaderPipeline : public IShaderPipeline blDesc.RenderTarget[0].BlendEnable = (dstFac != BlendFactor::Zero); blDesc.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)]; blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)]; + blDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; + blDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState)); const auto& vertBuf = m_vert.get().m_vtxBlob; @@ -1008,7 +1010,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue func(); } - float m_clearColor[4] = {0.0,0.0,0.0,1.0}; + float m_clearColor[4] = {0.0,0.0,0.0,0.0}; void setClearColor(const float rgba[4]) { m_clearColor[0] = rgba[0]; @@ -1336,7 +1338,7 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) { XXH64_state_t hashState; uint64_t srcHashes[2] = {}; diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index 0fa3481..86bcc1d 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -470,7 +470,6 @@ class D3D12TextureR : public ITextureR D3D12_CLEAR_VALUE colorClear = {}; colorClear.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - colorClear.Color[3] = 1.f; ThrowIfFailed(ctx->m_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &rtvresdesc, D3D12_RESOURCE_STATE_RENDER_TARGET, &colorClear, __uuidof(ID3D12Resource), &m_colorTex)); @@ -654,7 +653,7 @@ class D3D12ShaderPipeline : public IShaderPipeline D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline, const D3D12VertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), m_topology(PRIMITIVE_TABLE[int(prim)]) { @@ -685,6 +684,8 @@ class D3D12ShaderPipeline : public IShaderPipeline desc.BlendState.RenderTarget[0].BlendEnable = true; desc.BlendState.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)]; desc.BlendState.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)]; + desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; } desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); desc.RasterizerState.FrontCounterClockwise = TRUE; @@ -1260,7 +1261,7 @@ struct D3D12CommandQueue : IGraphicsCommandQueue func(); } - float m_clearColor[4] = {0.0,0.0,0.0,1.0}; + float m_clearColor[4] = {0.0,0.0,0.0,0.0}; void setClearColor(const float rgba[4]) { m_clearColor[0] = rgba[0]; @@ -1767,7 +1768,7 @@ public: ComPtr* vertBlobOut, ComPtr* fragBlobOut, ComPtr* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) { XXH64_state_t hashState; uint64_t srcHashes[2] = {}; diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 922f896..d235214 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -65,7 +65,7 @@ public: }; ThreadLocalPtr GLDataFactoryImpl::m_deferredData; -struct GLData : IGraphicsDataPriv +struct GLData : IGraphicsDataPriv { std::vector> m_SPs; std::vector> m_SBinds; @@ -78,9 +78,19 @@ struct GLData : IGraphicsDataPriv std::vector> m_VFmts; }; +struct GLPoolItem : IGraphicsDataPriv +{ + std::unique_ptr m_buf; +}; + struct GLPool : IGraphicsBufferPool { - std::unordered_map> m_DBufs; + std::unordered_set m_items; + ~GLPool() + { + for (auto& item : m_items) + item->decrement(); + } }; static const GLenum USE_TABLE[] = @@ -97,7 +107,8 @@ class GLGraphicsBufferS : public IGraphicsBufferS friend struct GLCommandQueue; GLuint m_buf; GLenum m_target; - GLGraphicsBufferS(BufferUse use, const void* data, size_t sz) + GLGraphicsBufferS(IGraphicsData* parent, BufferUse use, const void* data, size_t sz) + : IGraphicsBufferS(parent) { m_target = USE_TABLE[int(use)]; glGenBuffers(1, &m_buf); @@ -127,8 +138,9 @@ class GLGraphicsBufferD : public IGraphicsBufferD std::unique_ptr m_cpuBuf; size_t m_cpuSz = 0; int m_validMask = 0; - GLGraphicsBufferD(BufferUse use, size_t sz) - : m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) + GLGraphicsBufferD(IGraphicsData* parent, BufferUse use, size_t sz) + : boo::IGraphicsBufferD(parent), + m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) { glGenBuffers(3, m_bufs); for (int i=0 ; i<3 ; ++i) @@ -154,8 +166,9 @@ public: IGraphicsBufferS* GLDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { - GLGraphicsBufferS* retval = new GLGraphicsBufferS(use, data, stride * count); - GLDataFactoryImpl::m_deferredData->m_SBufs.emplace_back(retval); + GLData* d = GLDataFactoryImpl::m_deferredData.get(); + GLGraphicsBufferS* retval = new GLGraphicsBufferS(d, use, data, stride * count); + d->m_SBufs.emplace_back(retval); return retval; } @@ -163,8 +176,9 @@ class GLTextureS : public ITextureS { friend class GLDataFactory; GLuint m_tex; - GLTextureS(size_t width, size_t height, size_t mips, + GLTextureS(GLData* parent, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) + : ITextureS(parent) { const uint8_t* dataIt = static_cast(data); glGenTextures(1, &m_tex); @@ -241,8 +255,9 @@ class GLTextureSA : public ITextureSA { friend class GLDataFactory; GLuint m_tex; - GLTextureSA(size_t width, size_t height, size_t layers, size_t mips, + GLTextureSA(GLData* parent, size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) + : ITextureSA(parent) { const uint8_t* dataIt = static_cast(data); glGenTextures(1, &m_tex); @@ -302,7 +317,7 @@ class GLTextureD : public ITextureD size_t m_width = 0; size_t m_height = 0; int m_validMask = 0; - GLTextureD(size_t width, size_t height, TextureFormat fmt); + GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt); void update(int b); public: ~GLTextureD(); @@ -314,27 +329,29 @@ public: void bind(size_t idx, int b); }; +#define MAX_BIND_TEXS 4 + class GLTextureR : public ITextureR { friend class GLDataFactory; friend struct GLCommandQueue; struct GLCommandQueue* m_q; GLuint m_texs[2] = {}; - GLuint m_bindTexs[2] = {}; + GLuint m_bindTexs[2][MAX_BIND_TEXS] = {}; GLuint m_fbo = 0; size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; GLenum m_target; - GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples, - bool enableShaderColorBinding, bool enableShaderDepthBinding); + GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, + size_t colorBindCount, size_t depthBindCount); public: ~GLTextureR(); - void bind(size_t idx) const + void bind(size_t idx, int bindIdx, bool depth) const { glActiveTexture(GL_TEXTURE0 + idx); - glBindTexture(m_target, m_bindTexs[0]); + glBindTexture(m_target, m_bindTexs[depth][bindIdx]); } void resize(size_t width, size_t height) @@ -349,15 +366,22 @@ public: glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); - if (m_bindTexs[0]) + for (int i=0 ; im_STexs.emplace_back(retval); + GLData* d = GLDataFactoryImpl::m_deferredData.get(); + GLTextureS* retval = new GLTextureS(d, width, height, mips, fmt, data, sz); + d->m_STexs.emplace_back(retval); return retval; } @@ -398,8 +430,9 @@ ITextureSA* GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void *data, size_t sz) { - GLTextureSA* retval = new GLTextureSA(width, height, layers, mips, fmt, data, sz); - GLDataFactoryImpl::m_deferredData->m_SATexs.emplace_back(retval); + GLData* d = GLDataFactoryImpl::m_deferredData.get(); + GLTextureSA* retval = new GLTextureSA(d, width, height, layers, mips, fmt, data, sz); + d->m_SATexs.emplace_back(retval); return retval; } @@ -414,11 +447,13 @@ class GLShaderPipeline : public IShaderPipeline GLenum m_sfactor = GL_ONE; GLenum m_dfactor = GL_ZERO; GLenum m_drawPrim = GL_TRIANGLES; - bool m_depthTest = true; + ZTest m_depthTest = ZTest::LEqual; bool m_depthWrite = true; + bool m_colorWrite = true; + bool m_alphaWrite = true; CullMode m_culling; std::vector m_uniLocs; - GLShaderPipeline() = default; + GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {} public: operator bool() const {return m_prog != 0;} ~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); } @@ -435,11 +470,14 @@ public: m_drawPrim = other.m_drawPrim; m_depthTest = other.m_depthTest; m_depthWrite = other.m_depthWrite; + m_colorWrite = other.m_colorWrite; + m_alphaWrite = other.m_alphaWrite; m_culling = other.m_culling; m_uniLocs = std::move(other.m_uniLocs); return *this; } - GLShaderPipeline(GLShaderPipeline&& other) { *this = std::move(other); } + GLShaderPipeline(GLShaderPipeline&& other) + : IShaderPipeline(other.m_parentData) { *this = std::move(other); } GLuint bind() const { @@ -448,17 +486,32 @@ public: if (m_dfactor != GL_ZERO) { glEnable(GL_BLEND); - glBlendFunc(m_sfactor, m_dfactor); + glBlendFuncSeparate(m_sfactor, m_dfactor, GL_ONE, GL_ZERO); } else glDisable(GL_BLEND); - if (m_depthTest) + if (m_depthTest != ZTest::None) + { glEnable(GL_DEPTH_TEST); + switch (m_depthTest) + { + case ZTest::LEqual: + default: + glDepthFunc(GL_LEQUAL); + break; + case ZTest::Greater: + glDepthFunc(GL_GREATER); + break; + case ZTest::Equal: + glDepthFunc(GL_EQUAL); + break; + } + } else glDisable(GL_DEPTH_TEST); glDepthMask(m_depthWrite); - glDepthFunc(GL_LEQUAL); + glColorMask(m_colorWrite, m_colorWrite, m_colorWrite, m_alphaWrite); if (m_culling != CullMode::None) { @@ -499,10 +552,12 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline size_t texCount, const char** texNames, size_t uniformBlockCount, const char** uniformBlockNames, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { + GLData* d = GLDataFactoryImpl::m_deferredData.get(); GLDataFactoryImpl& factory = static_cast(m_parent); - GLShaderPipeline shader; + GLShaderPipeline shader(d); XXH64_state_t hashState; uint64_t hashes[2]; @@ -634,11 +689,13 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)]; shader.m_depthTest = depthTest; shader.m_depthWrite = depthWrite; + shader.m_colorWrite = colorWrite; + shader.m_alphaWrite = alphaWrite; shader.m_culling = culling; shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)]; GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); - GLDataFactoryImpl::m_deferredData->m_SPs.emplace_back(retval); + d->m_SPs.emplace_back(retval); return retval; } @@ -649,14 +706,14 @@ struct GLVertexFormat : IVertexFormat size_t m_elementCount; GLuint m_baseVert, m_baseInst; std::unique_ptr m_elements; - GLVertexFormat(GLCommandQueue* q, size_t elementCount, + GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst); ~GLVertexFormat(); void bind(int idx) const {glBindVertexArray(m_vao[idx]);} }; -struct GLShaderDataBinding : IShaderDataBindingPriv +struct GLShaderDataBinding : IShaderDataBindingPriv { const GLShaderPipeline* m_pipeline; const GLVertexFormat* m_vtxFormat; @@ -664,22 +721,32 @@ struct GLShaderDataBinding : IShaderDataBindingPriv std::unique_ptr m_ubufs; std::vector> m_ubufOffs; size_t m_texCount; - std::unique_ptr m_texs; + struct BoundTex + { + ITexture* tex; + int idx; + bool depth; + }; + std::unique_ptr m_texs; GLShaderDataBinding(GLData* d, IShaderPipeline* pipeline, IVertexFormat* vtxFormat, size_t ubufCount, IGraphicsBuffer** ubufs, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs) + size_t texCount, ITexture** texs, + const int* bindTexIdx, + const bool* depthBind) : IShaderDataBindingPriv(d), m_pipeline(static_cast(pipeline)), m_vtxFormat(static_cast(vtxFormat)), m_ubufCount(ubufCount), m_ubufs(new IGraphicsBuffer*[ubufCount]), m_texCount(texCount), - m_texs(new ITexture*[texCount]) + m_texs(new BoundTex[texCount]) { + addDepData(m_pipeline->m_parentData); + addDepData(m_vtxFormat->m_parentData); if (ubufOffs && ubufSizes) { m_ubufOffs.reserve(ubufCount); @@ -699,9 +766,15 @@ struct GLShaderDataBinding : IShaderDataBindingPriv Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i)); #endif m_ubufs[i] = ubufs[i]; + if (ubufs[i]) + addDepData(ubufs[i]->m_parentData); } for (size_t i=0 ; im_parentData); + } } void bind(int b) const { @@ -740,22 +813,22 @@ struct GLShaderDataBinding : IShaderDataBindingPriv } for (size_t i=0 ; itype()) + switch (tex.tex->type()) { case TextureType::Dynamic: - static_cast(tex)->bind(i, b); + static_cast(tex.tex)->bind(i, b); break; case TextureType::Static: - static_cast(tex)->bind(i); + static_cast(tex.tex)->bind(i); break; case TextureType::StaticArray: - static_cast(tex)->bind(i); + static_cast(tex.tex)->bind(i); break; case TextureType::Render: - static_cast(tex)->bind(i); + static_cast(tex.tex)->bind(i, tex.idx, tex.depth); break; default: break; } @@ -770,11 +843,13 @@ GLDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, 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) { GLShaderDataBinding* retval = new GLShaderDataBinding(GLDataFactoryImpl::m_deferredData.get(), pipeline, vtxFormat, ubufCount, ubufs, - ubufOffs, ubufSizes, texCount, texs); + ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind); GLDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval); return retval; } @@ -806,7 +881,7 @@ GraphicsDataToken GLDataFactoryImpl::commitTransaction(const FactoryCommitFunc& /* Let's go ahead and flush to ensure our data gets to the GPU While this isn't strictly required, some drivers might behave differently */ - glFlush(); + //glFlush(); return GraphicsDataToken(this, retval); } @@ -831,8 +906,8 @@ void GLDataFactoryImpl::destroyAllData() std::unique_lock lk(m_committedMutex); for (GLData* data : m_committedData) data->decrement(); - for (IGraphicsBufferPool* pool : m_committedPools) - delete static_cast(pool); + for (GLPool* pool : m_committedPools) + delete pool; m_committedData.clear(); m_committedPools.clear(); } @@ -849,15 +924,22 @@ IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, Buffe size_t stride, size_t count) { GLPool* pool = static_cast(p); - GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); - pool->m_DBufs.emplace(std::make_pair(retval, std::unique_ptr(retval))); + GLPoolItem* item = new GLPoolItem; + GLGraphicsBufferD* retval = new GLGraphicsBufferD(item, use, stride * count); + item->m_buf.reset(retval); + pool->m_items.emplace(item); return retval; } -void GLDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool *p, IGraphicsBufferD *buf) +void GLDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) { GLPool* 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); + } } static const GLint SEMANTIC_COUNT_TABLE[] = @@ -911,6 +993,13 @@ struct GLCommandQueue : IGraphicsCommandQueue const SystemChar* platformName() const {return _S("OpenGL");} IGraphicsContext* m_parent = nullptr; + std::mutex m_mt; + std::condition_variable m_cv; + std::mutex m_initmt; + std::condition_variable m_initcv; + std::unique_lock m_initlk; + std::thread m_thr; + struct Command { enum class Op @@ -947,8 +1036,9 @@ struct GLCommandQueue : IGraphicsCommandQueue size_t instCount; }; }; - IShaderDataBindingPriv::Token resToken; + IShaderDataBindingPriv::Token resToken; const ITextureR* resolveTex; + int bindIdx; bool resolveColor : 1; bool resolveDepth : 1; Command(Op op) : m_op(op) {} @@ -963,13 +1053,6 @@ struct GLCommandQueue : IGraphicsCommandQueue size_t m_drawBuf = 0; bool m_running = true; - std::mutex m_mt; - std::condition_variable m_cv; - std::mutex m_initmt; - std::condition_variable m_initcv; - std::unique_lock m_initlk; - std::thread m_thr; - struct RenderTextureResize { GLTextureR* tex; @@ -1064,6 +1147,7 @@ struct GLCommandQueue : IGraphicsCommandQueue const GLubyte* version = glGetString(GL_VERSION); Log.report(logvisor::Info, "OpenGL Version: %s", version); self->m_parent->postInit(); + glClearColor(0.f, 0.f, 0.f, 0.f); } self->m_initcv.notify_one(); while (self->m_running) @@ -1157,6 +1241,8 @@ struct GLCommandQueue : IGraphicsCommandQueue glClearColor(cmd.rgba[0], cmd.rgba[1], cmd.rgba[2], cmd.rgba[3]); break; case Command::Op::ClearTarget: + if (cmd.flags & GL_COLOR_BUFFER_BIT) + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); if (cmd.flags & GL_DEPTH_BUFFER_BIT) glDepthMask(GL_TRUE); glClear(cmd.flags); @@ -1181,16 +1267,16 @@ struct GLCommandQueue : IGraphicsCommandQueue GLenum target = (tex->m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); glActiveTexture(GL_TEXTURE9); - if (cmd.resolveColor && tex->m_bindTexs[0]) + if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx]) { - glBindTexture(target, tex->m_bindTexs[0]); + glBindTexture(target, tex->m_bindTexs[0][cmd.bindIdx]); glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); } - if (cmd.resolveDepth && tex->m_bindTexs[1]) + if (cmd.resolveDepth && tex->m_bindTexs[1][cmd.bindIdx]) { - glBindTexture(target, tex->m_bindTexs[1]); + glBindTexture(target, tex->m_bindTexs[1][cmd.bindIdx]); glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); @@ -1230,14 +1316,20 @@ struct GLCommandQueue : IGraphicsCommandQueue void stopRenderer() { - m_running = false; - m_cv.notify_one(); - m_thr.join(); + if (m_running) + { + m_running = false; + m_cv.notify_one(); + if (m_thr.joinable()) + m_thr.join(); + for (int i=0 ; i<3 ; ++i) + m_cmdBufs[i].clear(); + } } ~GLCommandQueue() { - if (m_running) stopRenderer(); + stopRenderer(); } void setShaderDataBinding(IShaderDataBinding* binding) @@ -1245,7 +1337,7 @@ struct GLCommandQueue : IGraphicsCommandQueue std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::SetShaderDataBinding); cmds.back().binding = binding; - cmds.back().resToken = static_cast*>(binding)->lock(); + cmds.back().resToken = static_cast(binding)->lock(); } void setRenderTarget(ITextureR* target) @@ -1338,12 +1430,14 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().instCount = instCount; } - 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) { GLTextureR* tex = static_cast(texture); std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::ResolveBindTexture); cmds.back().resolveTex = texture; + cmds.back().bindIdx = bindIdx; cmds.back().resolveColor = color; cmds.back().resolveDepth = depth; SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height)); @@ -1421,11 +1515,11 @@ struct GLCommandQueue : IGraphicsCommandQueue } for (GLPool* p : gfxF->m_committedPools) { - for (auto& b : p->m_DBufs) - b.second->update(m_completeBuf); + for (auto& b : p->m_items) + b->m_buf->update(m_completeBuf); } datalk.unlock(); - glFlush(); + //glFlush(); for (auto& p : m_pendingPosts1) m_pendingPosts2.push_back(std::move(p)); @@ -1476,13 +1570,14 @@ void GLGraphicsBufferD::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr si IGraphicsBufferD* GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) { - GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); - GLDataFactoryImpl::m_deferredData->m_DBufs.emplace_back(retval); + GLData* d = GLDataFactoryImpl::m_deferredData.get(); + GLGraphicsBufferD* retval = new GLGraphicsBufferD(d, use, stride * count); + d->m_DBufs.emplace_back(retval); return retval; } -GLTextureD::GLTextureD(size_t width, size_t height, TextureFormat fmt) -: m_width(width), m_height(height) +GLTextureD::GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt) +: boo::ITextureD(parent), m_width(width), m_height(height) { int pxPitch = 4; switch (fmt) @@ -1551,20 +1646,29 @@ void GLTextureD::bind(size_t idx, int b) ITextureD* GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { - GLTextureD* retval = new GLTextureD(width, height, fmt); - GLDataFactoryImpl::m_deferredData->m_DTexs.emplace_back(retval); + GLData* d = GLDataFactoryImpl::m_deferredData.get(); + GLTextureD* retval = new GLTextureD(d, width, height, fmt); + d->m_DTexs.emplace_back(retval); return retval; } -GLTextureR::GLTextureR(GLCommandQueue* 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) +GLTextureR::GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, + size_t colorBindingCount, size_t depthBindingCount) +: boo::ITextureR(parent), m_q(q), m_width(width), m_height(height), m_samples(samples) { glGenTextures(2, m_texs); - if (enableShaderColorBinding) - glGenTextures(1, &m_bindTexs[0]); - if (enableShaderDepthBinding) - glGenTextures(1, &m_bindTexs[1]); + if (colorBindingCount) + { + if (colorBindingCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many color bindings for render texture"); + glGenTextures(colorBindingCount, m_bindTexs[0]); + } + if (depthBindingCount) + { + if (depthBindingCount > MAX_BIND_TEXS) + Log.report(logvisor::Fatal, "too many depth bindings for render texture"); + glGenTextures(depthBindingCount, m_bindTexs[1]); + } if (samples > 1) { m_target = GL_TEXTURE_2D_MULTISAMPLE; @@ -1573,14 +1677,15 @@ GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t sa glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); - if (enableShaderColorBinding) + for (int i=0 ; idelFBO(this); } ITextureR* GLDataFactory::Context::newRenderTexture(size_t width, size_t height, - bool enableShaderColorBinding, bool enableShaderDepthBinding) + size_t colorBindingCount, size_t depthBindingCount) { + GLData* d = GLDataFactoryImpl::m_deferredData.get(); GLDataFactoryImpl& factory = static_cast(m_parent); GLCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - GLTextureR* retval = new GLTextureR(q, width, height, factory.m_drawSamples, - enableShaderColorBinding, enableShaderDepthBinding); + GLTextureR* retval = new GLTextureR(d, q, width, height, factory.m_drawSamples, + colorBindingCount, depthBindingCount); q->resizeRenderTexture(retval, width, height); GLDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval); return retval; } -GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount, +GLVertexFormat::GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) -: m_q(q), +: boo::IVertexFormat(parent), + m_q(q), m_elementCount(elementCount), m_elements(new VertexElementDescriptor[elementCount]), m_baseVert(baseVert), m_baseInst(baseInst) @@ -1647,10 +1754,11 @@ IVertexFormat* GLDataFactory::Context::newVertexFormat (size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) { + GLData* d = GLDataFactoryImpl::m_deferredData.get(); GLDataFactoryImpl& factory = static_cast(m_parent); GLCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements, baseVert, baseInst); - GLDataFactoryImpl::m_deferredData->m_VFmts.emplace_back(retval); + GLVertexFormat* retval = new struct GLVertexFormat(d, q, elementCount, elements, baseVert, baseInst); + d->m_VFmts.emplace_back(retval); return retval; } diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index 3e22828..4718507 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -62,7 +62,7 @@ public: }; ThreadLocalPtr MetalDataFactoryImpl::m_deferredData; -struct MetalData : IGraphicsDataPriv +struct MetalData : IGraphicsDataPriv { std::vector> m_SPs; std::vector> m_SBinds; @@ -75,9 +75,19 @@ struct MetalData : IGraphicsDataPriv std::vector> m_VFmts; }; +struct MetalPoolItem : IGraphicsDataPriv +{ + std::unique_ptr m_buf; +}; + struct MetalPool : IGraphicsBufferPool { - std::unordered_map> m_DBufs; + std::unordered_set m_items; + ~MetalPool() + { + for (auto& item : m_items) + item->decrement(); + } }; #define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared @@ -87,8 +97,9 @@ class MetalGraphicsBufferS : public IGraphicsBufferS { friend class MetalDataFactory; friend struct MetalCommandQueue; - MetalGraphicsBufferS(BufferUse use, MetalContext* ctx, const void* data, size_t stride, size_t count) - : m_stride(stride), m_count(count), m_sz(stride * count) + MetalGraphicsBufferS(IGraphicsData* parent, BufferUse use, MetalContext* ctx, + const void* data, size_t stride, size_t count) + : boo::IGraphicsBufferS(parent), m_stride(stride), m_count(count), m_sz(stride * count) { m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC]; } @@ -108,8 +119,9 @@ class MetalGraphicsBufferD : public IGraphicsBufferD MetalCommandQueue* m_q; std::unique_ptr m_cpuBuf; int m_validSlots = 0; - MetalGraphicsBufferD(MetalCommandQueue* q, BufferUse use, MetalContext* ctx, size_t stride, size_t count) - : m_q(q), m_stride(stride), m_count(count), m_sz(stride * count) + MetalGraphicsBufferD(IGraphicsData* parent, MetalCommandQueue* q, BufferUse use, + MetalContext* ctx, size_t stride, size_t count) + : boo::IGraphicsBufferD(parent), m_q(q), m_stride(stride), m_count(count), m_sz(stride * count) { m_cpuBuf.reset(new uint8_t[m_sz]); m_bufs[0] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC]; @@ -131,8 +143,9 @@ public: class MetalTextureS : public ITextureS { friend class MetalDataFactory; - MetalTextureS(MetalContext* ctx, size_t width, size_t height, size_t mips, + MetalTextureS(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) + : ITextureS(parent) { MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; NSUInteger ppitchNum = 4; @@ -182,8 +195,10 @@ public: class MetalTextureSA : public ITextureSA { friend class MetalDataFactory; - MetalTextureSA(MetalContext* ctx, size_t width, size_t height, size_t layers, size_t mips, + MetalTextureSA(IGraphicsData* parent, MetalContext* ctx, size_t width, + size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) + : ITextureSA(parent) { MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; NSUInteger ppitch = 4; @@ -243,8 +258,9 @@ class MetalTextureD : public ITextureD size_t m_cpuSz; size_t m_pxPitch; int m_validSlots = 0; - MetalTextureD(MetalCommandQueue* q, MetalContext* ctx, size_t width, size_t height, TextureFormat fmt) - : m_q(q), m_width(width), m_height(height) + MetalTextureD(IGraphicsData* parent, MetalCommandQueue* q, MetalContext* ctx, + size_t width, size_t height, TextureFormat fmt) + : boo::ITextureD(parent), m_q(q), m_width(width), m_height(height) { MTLPixelFormat format; switch (fmt) @@ -285,6 +301,8 @@ public: void unmap(); }; +#define MAX_BIND_TEXS 4 + class MetalTextureR : public ITextureR { friend class MetalDataFactory; @@ -292,14 +310,20 @@ class MetalTextureR : public ITextureR size_t m_width = 0; size_t m_height = 0; size_t m_samples = 0; - bool m_enableShaderBindTexture; + size_t m_colorBindCount; + size_t m_depthBindCount; void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples, - bool enableShaderBindTexture) + size_t colorBindCount, size_t depthBindCount) { m_width = width; m_height = height; + 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"); + @autoreleasepool { MTLTextureDescriptor* desc = @@ -315,15 +339,23 @@ class MetalTextureR : public ITextureR desc.usage = MTLTextureUsageRenderTarget; m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc]; - if (enableShaderBindTexture) + if (colorBindCount) { desc.usage = MTLTextureUsageShaderRead; - m_colorBindTex = [ctx->m_dev newTextureWithDescriptor:desc]; + for (int i=0 ; im_dev newTextureWithDescriptor:desc]; } desc.usage = MTLTextureUsageRenderTarget; desc.pixelFormat = MTLPixelFormatDepth32Float; m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; + + if (depthBindCount) + { + desc.usage = MTLTextureUsageShaderRead; + for (int i=0 ; im_dev newTextureWithDescriptor:desc]; + } } else { @@ -332,15 +364,23 @@ class MetalTextureR : public ITextureR desc.usage = MTLTextureUsageRenderTarget; m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc]; - if (enableShaderBindTexture) + if (colorBindCount) { desc.usage = MTLTextureUsageShaderRead; - m_colorBindTex = [ctx->m_dev newTextureWithDescriptor:desc]; + for (int i=0 ; im_dev newTextureWithDescriptor:desc]; } desc.usage = MTLTextureUsageRenderTarget; desc.pixelFormat = MTLPixelFormatDepth32Float; m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; + + if (depthBindCount) + { + desc.usage = MTLTextureUsageShaderRead; + for (int i=0 ; im_dev newTextureWithDescriptor:desc]; + } } { @@ -375,6 +415,7 @@ class MetalTextureR : public ITextureR m_clearColorPassDesc.colorAttachments[0].texture = m_colorTex; m_clearColorPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; m_clearColorPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore; + m_clearDepthPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0); m_clearColorPassDesc.depthAttachment.texture = m_depthTex; m_clearColorPassDesc.depthAttachment.loadAction = MTLLoadActionLoad; @@ -388,6 +429,7 @@ class MetalTextureR : public ITextureR m_clearBothPassDesc.colorAttachments[0].texture = m_colorTex; m_clearBothPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; m_clearBothPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore; + m_clearBothPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0); m_clearBothPassDesc.depthAttachment.texture = m_depthTex; m_clearBothPassDesc.depthAttachment.loadAction = MTLLoadActionClear; @@ -397,18 +439,21 @@ class MetalTextureR : public ITextureR } } - MetalTextureR(MetalContext* ctx, size_t width, size_t height, size_t samples, - bool enableShaderBindTexture) - : m_width(width), m_height(height), m_samples(samples), m_enableShaderBindTexture(enableShaderBindTexture) + MetalTextureR(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t samples, + size_t colorBindCount, size_t depthBindCount) + : boo::ITextureR(parent), m_width(width), m_height(height), m_samples(samples), + m_colorBindCount(colorBindCount), + m_depthBindCount(depthBindCount) { if (samples == 0) m_samples = 1; - Setup(ctx, width, height, samples, enableShaderBindTexture); + Setup(ctx, width, height, samples, colorBindCount, depthBindCount); } public: size_t samples() const {return m_samples;} id m_colorTex; id m_depthTex; - id m_colorBindTex; + id m_colorBindTex[MAX_BIND_TEXS] = {}; + id m_depthBindTex[MAX_BIND_TEXS] = {}; MTLRenderPassDescriptor* m_passDesc; MTLRenderPassDescriptor* m_clearDepthPassDesc; MTLRenderPassDescriptor* m_clearColorPassDesc; @@ -423,7 +468,7 @@ public: height = 1; m_width = width; m_height = height; - Setup(ctx, width, height, m_samples, m_enableShaderBindTexture); + Setup(ctx, width, height, m_samples, m_colorBindCount, m_depthBindCount); } }; @@ -463,8 +508,8 @@ struct MetalVertexFormat : IVertexFormat MTLVertexDescriptor* m_vdesc; size_t m_stride = 0; size_t m_instStride = 0; - MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) - : m_elementCount(elementCount) + MetalVertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements) + : boo::IVertexFormat(parent), m_elementCount(elementCount) { for (size_t i=0 ; im_vdesc; desc.sampleCount = targetSamples; desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; + desc.colorAttachments[0].writeMask = (colorWrite ? COLOR_WRITE_MASK : 0) | + (alphaWrite ? MTLColorWriteMaskAlpha : 0); desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero; desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; + desc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; + desc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero; desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; NSError* err = nullptr; @@ -590,8 +644,23 @@ class MetalShaderPipeline : public IShaderPipeline [[err localizedDescription] UTF8String]); MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; - if (depthTest) + switch (depthTest) + { + case ZTest::None: + default: + dsDesc.depthCompareFunction = MTLCompareFunctionAlways; + break; + case ZTest::LEqual: dsDesc.depthCompareFunction = MTLCompareFunctionGreaterEqual; + break; + case ZTest::Greater: + dsDesc.depthCompareFunction = MTLCompareFunctionLess; + break; + case ZTest::Equal: + dsDesc.depthCompareFunction = MTLCompareFunctionEqual; + break; + } + dsDesc.depthWriteEnabled = depthWrite; m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc]; } @@ -624,7 +693,23 @@ static id GetBufferGPUResource(const IGraphicsBuffer* buf, int idx) } } -static id GetTextureGPUResource(const ITexture* tex, int idx) +static id GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, size_t& strideOut) +{ + if (buf->dynamic()) + { + const MetalGraphicsBufferD* cbuf = static_cast(buf); + strideOut = cbuf->m_stride; + return cbuf->m_bufs[idx]; + } + else + { + const MetalGraphicsBufferS* cbuf = static_cast(buf); + strideOut = cbuf->m_stride; + return cbuf->m_buf; + } +} + +static id GetTextureGPUResource(const ITexture* tex, int idx, int bindIdx, bool depth) { switch (tex->type()) { @@ -646,14 +731,14 @@ static id GetTextureGPUResource(const ITexture* tex, int idx) case TextureType::Render: { const MetalTextureR* ctex = static_cast(tex); - return ctex->m_colorBindTex; + return depth ? ctex->m_depthBindTex[bindIdx] : ctex->m_colorBindTex[bindIdx]; } default: break; } return nullptr; } -struct MetalShaderDataBinding : IShaderDataBindingPriv +struct MetalShaderDataBinding : IShaderDataBindingPriv { MetalShaderPipeline* m_pipeline; IGraphicsBuffer* m_vbuf; @@ -664,7 +749,13 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv std::unique_ptr m_ubufOffs; std::unique_ptr m_fubufs; size_t m_texCount; - std::unique_ptr m_texs; + struct BoundTex + { + ITexture* tex; + int idx; + bool depth; + }; + std::unique_ptr m_texs; size_t m_baseVert; size_t m_baseInst; @@ -674,7 +765,9 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv 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 baseVert, size_t baseInst) + size_t texCount, ITexture** texs, + const int* texBindIdxs, const bool* depthBind, + size_t baseVert, size_t baseInst) : IShaderDataBindingPriv(d), m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), @@ -683,10 +776,12 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv m_ubufCount(ubufCount), m_ubufs(new IGraphicsBuffer*[ubufCount]), m_texCount(texCount), - m_texs(new ITexture*[texCount]), + m_texs(new BoundTex[texCount]), m_baseVert(baseVert), m_baseInst(baseInst) { + addDepData(m_pipeline->m_parentData); + if (ubufCount && ubufStages) { m_fubufs.reset(new bool[ubufCount]); @@ -713,10 +808,14 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i)); #endif m_ubufs[i] = ubufs[i]; + if (ubufs[i]) + addDepData(ubufs[i]->m_parentData); } for (size_t i=0 ; im_parentData); } } @@ -724,12 +823,17 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv { m_pipeline->bind(enc); + size_t stride; if (m_vbuf) - [enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b) - offset:m_pipeline->m_vtxFmt->m_stride * m_baseVert atIndex:0]; + { + id buf = GetBufferGPUResource(m_vbuf, b, stride); + [enc setVertexBuffer:buf offset:stride * m_baseVert atIndex:0]; + } if (m_instVbo) - [enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b) - offset:m_pipeline->m_vtxFmt->m_instStride * m_baseInst atIndex:1]; + { + id buf = GetBufferGPUResource(m_instVbo, b, stride); + [enc setVertexBuffer:buf offset:stride * m_baseInst atIndex:1]; + } if (m_ubufOffs) for (size_t i=0 ; i [enc setVertexBuffer:GetBufferGPUResource(m_ubufs[i], b) offset:0 atIndex:i+2]; } for (size_t i=0 ; i(target); - [m_enc endEncoding]; @autoreleasepool { + [m_enc endEncoding]; if (clearColor && clearDepth) m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_clearBothPassDesc]; else if (clearColor) @@ -865,7 +969,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue void flushBufferUpdates() {} - float m_clearColor[4] = {0.0,0.0,0.0,1.0}; + float m_clearColor[4] = {0.0,0.0,0.0,0.0}; void setClearColor(const float rgba[4]) { m_clearColor[0] = rgba[0]; @@ -911,36 +1015,53 @@ struct MetalCommandQueue : IGraphicsCommandQueue instanceCount:instCount]; } - 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) { MetalTextureR* tex = static_cast(texture); - if (color && tex->m_enableShaderBindTexture) + @autoreleasepool { [m_enc endEncoding]; - @autoreleasepool + SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height)); + NSUInteger y = tlOrigin ? intersectRect.location[1] : int(tex->m_height) - + intersectRect.location[1] - intersectRect.size[1]; + MTLOrigin origin = {NSUInteger(intersectRect.location[0]), y, 0}; + id blitEnc = [m_cmdBuf blitCommandEncoder]; + + if (color && tex->m_colorBindTex[bindIdx]) { - SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height)); - NSUInteger y = tlOrigin ? intersectRect.location[1] : int(tex->m_height) - intersectRect.location[1] - intersectRect.size[1]; - MTLOrigin origin = {NSUInteger(intersectRect.location[0]), y, 0}; - id blitEnc = [m_cmdBuf blitCommandEncoder]; [blitEnc copyFromTexture:tex->m_colorTex sourceSlice:0 sourceLevel:0 sourceOrigin:origin sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1) - toTexture:tex->m_colorBindTex + toTexture:tex->m_colorBindTex[bindIdx] destinationSlice:0 destinationLevel:0 destinationOrigin:origin]; - [blitEnc endEncoding]; - m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_passDesc]; - [m_enc setFrontFacingWinding:MTLWindingCounterClockwise]; - - if (m_boundVp.width || m_boundVp.height) - [m_enc setViewport:m_boundVp]; - if (m_boundScissor.width || m_boundScissor.height) - [m_enc setScissorRect:m_boundScissor]; } + + if (depth && tex->m_depthBindTex[bindIdx]) + { + [blitEnc copyFromTexture:tex->m_depthTex + sourceSlice:0 + sourceLevel:0 + sourceOrigin:origin + sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1) + toTexture:tex->m_depthBindTex[bindIdx] + destinationSlice:0 + destinationLevel:0 + destinationOrigin:origin]; + } + + [blitEnc endEncoding]; + m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_passDesc]; + [m_enc setFrontFacingWinding:MTLWindingCounterClockwise]; + + if (m_boundVp.width || m_boundVp.height) + [m_enc setViewport:m_boundVp]; + if (m_boundScissor.width || m_boundScissor.height) + [m_enc setScissorRect:m_boundScissor]; } } @@ -968,8 +1089,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue } for (MetalPool* p : gfxF->m_committedPools) { - for (auto& b : p->m_DBufs) - b.second->update(m_fillBuf); + for (auto& b : p->m_items) + b->m_buf->update(m_fillBuf); } datalk.unlock(); @@ -999,38 +1120,35 @@ struct MetalCommandQueue : IGraphicsCommandQueue if (m_needsDisplay) { MetalContext::Window& w = m_ctx->m_windows[m_parentWindow]; - @autoreleasepool { + std::unique_lock lk(w.m_resizeLock); + if (w.m_needsResize) { - std::unique_lock lk(w.m_resizeLock); - if (w.m_needsResize) - { - w.m_metalLayer.drawableSize = w.m_size; - w.m_needsResize = NO; - m_needsDisplay = nullptr; - return; - } + w.m_metalLayer.drawableSize = w.m_size; + w.m_needsResize = NO; + m_needsDisplay = nullptr; + return; } - id drawable = [w.m_metalLayer nextDrawable]; - if (drawable) + } + id drawable = [w.m_metalLayer nextDrawable]; + if (drawable) + { + id dest = drawable.texture; + if (m_needsDisplay->m_colorTex.width == dest.width && + m_needsDisplay->m_colorTex.height == dest.height) { - id dest = drawable.texture; - if (m_needsDisplay->m_colorTex.width == dest.width && - m_needsDisplay->m_colorTex.height == dest.height) - { - id blitEnc = [m_cmdBuf blitCommandEncoder]; - [blitEnc copyFromTexture:m_needsDisplay->m_colorTex - sourceSlice:0 - sourceLevel:0 - sourceOrigin:MTLOriginMake(0, 0, 0) - sourceSize:MTLSizeMake(dest.width, dest.height, 1) - toTexture:dest - destinationSlice:0 - destinationLevel:0 - destinationOrigin:MTLOriginMake(0, 0, 0)]; - [blitEnc endEncoding]; - [m_cmdBuf presentDrawable:drawable]; - } + id blitEnc = [m_cmdBuf blitCommandEncoder]; + [blitEnc copyFromTexture:m_needsDisplay->m_colorTex + sourceSlice:0 + sourceLevel:0 + sourceOrigin:MTLOriginMake(0, 0, 0) + sourceSize:MTLSizeMake(dest.width, dest.height, 1) + toTexture:dest + destinationSlice:0 + destinationLevel:0 + destinationOrigin:MTLOriginMake(0, 0, 0)]; + [blitEnc endEncoding]; + [m_cmdBuf presentDrawable:drawable]; } } m_needsDisplay = nullptr; @@ -1107,66 +1225,76 @@ MetalDataFactoryImpl::MetalDataFactoryImpl(IGraphicsContext* parent, MetalContex IGraphicsBufferS* MetalDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); - MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(use, factory.m_ctx, data, stride, count); - MetalDataFactoryImpl::m_deferredData->m_SBufs.emplace_back(retval); + MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(d, use, factory.m_ctx, data, stride, count); + d->m_SBufs.emplace_back(retval); return retval; } IGraphicsBufferD* MetalDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); MetalCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, factory.m_ctx, stride, count); - MetalDataFactoryImpl::m_deferredData->m_DBufs.emplace_back(retval); + MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(d, q, use, factory.m_ctx, stride, count); + d->m_DBufs.emplace_back(retval); return retval; } ITextureS* MetalDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); - MetalTextureS* retval = new MetalTextureS(factory.m_ctx, width, height, mips, fmt, data, sz); - MetalDataFactoryImpl::m_deferredData->m_STexs.emplace_back(retval); + MetalTextureS* retval = new MetalTextureS(d, factory.m_ctx, width, height, mips, fmt, data, sz); + d->m_STexs.emplace_back(retval); return retval; } ITextureSA* MetalDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, const void* data, size_t sz) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); - MetalTextureSA* retval = new MetalTextureSA(factory.m_ctx, width, height, layers, mips, fmt, data, sz); - MetalDataFactoryImpl::m_deferredData->m_SATexs.emplace_back(retval); + MetalTextureSA* retval = new MetalTextureSA(d, factory.m_ctx, width, height, layers, mips, fmt, data, sz); + d->m_SATexs.emplace_back(retval); return retval; } ITextureD* MetalDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); MetalCommandQueue* q = static_cast(factory.m_parent->getCommandQueue()); - MetalTextureD* retval = new MetalTextureD(q, factory.m_ctx, width, height, fmt); - MetalDataFactoryImpl::m_deferredData->m_DTexs.emplace_back(retval); + MetalTextureD* retval = new MetalTextureD(d, q, factory.m_ctx, width, height, fmt); + d->m_DTexs.emplace_back(retval); return retval; } ITextureR* MetalDataFactory::Context::newRenderTexture(size_t width, size_t height, - bool enableShaderColorBinding, bool enableShaderDepthBinding) + size_t colorBindCount, size_t depthBindCount) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); - MetalTextureR* retval = new MetalTextureR(factory.m_ctx, width, height, factory.m_sampleCount, enableShaderColorBinding); - MetalDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval); + MetalTextureR* retval = new MetalTextureR(d, factory.m_ctx, width, height, factory.m_sampleCount, + colorBindCount, depthBindCount); + d->m_RTexs.emplace_back(retval); return retval; } IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) { - MetalVertexFormat* retval = new struct MetalVertexFormat(elementCount, elements); - MetalDataFactoryImpl::m_deferredData->m_VFmts.emplace_back(retval); + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); + MetalVertexFormat* retval = new struct MetalVertexFormat(d, elementCount, elements); + d->m_VFmts.emplace_back(retval); return retval; } IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, unsigned targetSamples, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling) { + MetalData* d = MetalDataFactoryImpl::m_deferredData.get(); MetalDataFactoryImpl& factory = static_cast(m_parent); MTLCompileOptions* compOpts = [MTLCompileOptions new]; compOpts.languageVersion = MTLLanguageVersion1_1; @@ -1228,10 +1356,11 @@ IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSo fragShader = it->second->lock(); } - MetalShaderPipeline* retval = new MetalShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader), + MetalShaderPipeline* retval = new MetalShaderPipeline(d, factory.m_ctx, std::move(vertShader), std::move(fragShader), static_cast(vtxFmt), targetSamples, - srcFac, dstFac, prim, depthTest, depthWrite, culling); - MetalDataFactoryImpl::m_deferredData->m_SPs.emplace_back(retval); + srcFac, dstFac, prim, depthTest, depthWrite, + colorWrite, alphaWrite, culling); + d->m_SPs.emplace_back(retval); return retval; } @@ -1241,14 +1370,17 @@ MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline, 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 baseVert, size_t baseInst) + size_t texCount, ITexture** texs, + const int* texBindIdxs, const bool* depthBind, + size_t baseVert, size_t baseInst) { MetalDataFactoryImpl& factory = static_cast(m_parent); MetalShaderDataBinding* retval = new MetalShaderDataBinding(MetalDataFactoryImpl::m_deferredData.get(), factory.m_ctx, pipeline, vbuf, instVbo, ibuf, ubufCount, ubufs, ubufStages, ubufOffs, - ubufSizes, texCount, texs, baseVert, baseInst); + ubufSizes, texCount, texs, texBindIdxs, + depthBind, baseVert, baseInst); MetalDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval); return retval; } @@ -1295,8 +1427,8 @@ void MetalDataFactoryImpl::destroyAllData() std::unique_lock lk(m_committedMutex); for (MetalData* data : m_committedData) data->decrement(); - for (IGraphicsBufferPool* pool : m_committedPools) - delete static_cast(pool); + for (MetalPool* pool : m_committedPools) + delete pool; m_committedData.clear(); m_committedPools.clear(); } @@ -1314,15 +1446,22 @@ IGraphicsBufferD* MetalDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, Bu { MetalPool* pool = static_cast(p); MetalCommandQueue* q = static_cast(m_parent->getCommandQueue()); - MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, m_ctx, stride, count); - pool->m_DBufs.emplace(std::make_pair(retval, std::unique_ptr(retval))); + MetalPoolItem* item = new MetalPoolItem; + MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(item, q, use, m_ctx, stride, count); + item->m_buf.reset(retval); + pool->m_items.emplace(item); return retval; } void MetalDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) { MetalPool* 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); + } } IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index 2c14600..2f80269 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -1841,7 +1841,7 @@ class VulkanShaderPipeline : public IShaderPipeline VkPipelineCache pipelineCache, const VulkanVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) : m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_frag(std::move(frag)) { @@ -2509,7 +2509,7 @@ struct VulkanCommandQueue : IGraphicsCommandQueue func(); } - float m_clearColor[4] = {0.0,0.0,0.0,1.0}; + float m_clearColor[4] = {0.0,0.0,0.0,0.0}; void setClearColor(const float rgba[4]) { m_clearColor[0] = rgba[0]; @@ -3081,7 +3081,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline std::vector* vertBlobOut, std::vector* fragBlobOut, std::vector* pipelineBlob, IVertexFormat* vtxFmt, BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - bool depthTest, bool depthWrite, CullMode culling) + ZTest depthTest, bool depthWrite, CullMode culling) { VulkanDataFactoryImpl& factory = static_cast(m_parent); diff --git a/lib/mac/WindowCocoa.mm b/lib/mac/WindowCocoa.mm index 9211b72..f8fc134 100644 --- a/lib/mac/WindowCocoa.mm +++ b/lib/mac/WindowCocoa.mm @@ -214,8 +214,10 @@ public: ~GraphicsContextCocoaGL() { - delete m_dataFactory; + m_commandQueue->stopRenderer(); + m_dataFactory->destroyAllData(); delete m_commandQueue; + delete m_dataFactory; } void _setCallback(IWindowCallback* cb) @@ -370,8 +372,10 @@ public: ~GraphicsContextCocoaMetal() { - delete m_dataFactory; + m_commandQueue->stopRenderer(); + m_dataFactory->destroyAllData(); delete m_commandQueue; + delete m_dataFactory; m_metalCtx->m_windows.erase(m_parentWindow); } diff --git a/test/main.cpp b/test/main.cpp index feec53e..bd51847 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -308,7 +308,7 @@ struct TestApplicationCallback : IApplicationCallback pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr, BlendFactor::One, BlendFactor::Zero, - Primitive::TriStrips, true, true, CullMode::None); + Primitive::TriStrips, boo::ZTest::LEqual, true, true, false, CullMode::None); } #if BOO_HAS_VULKAN else if (plat == IGraphicsDataFactory::Platform::Vulkan) @@ -403,13 +403,14 @@ struct TestApplicationCallback : IApplicationCallback pipeline = metalF.newShaderPipeline(VS, FS, vfmt, 1, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, - true, true, boo::CullMode::None); + boo::ZTest::LEqual, true, true, true, boo::CullMode::None); } #endif /* Make shader data binding */ self->m_binding = - ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, nullptr, 1, &texture); + ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, nullptr, + 1, &texture, nullptr, nullptr); return true; });