From 021143fd89fa179a4610996b744331967c0d6e8c Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 2 Nov 2017 23:39:26 -1000 Subject: [PATCH] New object management architecture for OpenGL subsystem (more platforms to come) --- CMakeLists.txt | 1 + include/boo/BooObject.hpp | 47 ++ include/boo/graphicsdev/GL.hpp | 59 +- .../boo/graphicsdev/IGraphicsCommandQueue.hpp | 10 +- .../boo/graphicsdev/IGraphicsDataFactory.hpp | 330 +++------- include/boo/graphicsdev/Metal.hpp | 54 +- lib/graphicsdev/Common.hpp | 238 +++++-- lib/graphicsdev/GL.cpp | 593 ++++++------------ lib/graphicsdev/Metal.mm | 247 +++----- logvisor | 2 +- 10 files changed, 692 insertions(+), 889 deletions(-) create mode 100644 include/boo/BooObject.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c2d91e..dd9548a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,6 +285,7 @@ add_library(boo include/boo/ThreadLocalPtr.hpp include/boo/DeferredWindowEvents.hpp include/boo/System.hpp + include/boo/BooObject.hpp include/boo/boo.hpp InputDeviceClasses.cpp ${PLAT_SRCS} diff --git a/include/boo/BooObject.hpp b/include/boo/BooObject.hpp new file mode 100644 index 0000000..89ab27c --- /dev/null +++ b/include/boo/BooObject.hpp @@ -0,0 +1,47 @@ +#ifndef BOOOBJECT_HPP +#define BOOOBJECT_HPP + +#include + +namespace boo +{ + +class IObj +{ + std::atomic_int m_refCount = {0}; +public: + virtual ~IObj() = default; + void increment() { m_refCount++; } + void decrement() + { + if (m_refCount.fetch_sub(1) == 1) + delete this; + } +}; + +template +class ObjToken +{ + SubCls* m_obj = nullptr; +public: + ObjToken() = default; + ObjToken(SubCls* obj) : m_obj(obj) { m_obj->increment(); } + ObjToken(const ObjToken& other) : m_obj(other.m_obj) { m_obj->increment(); } + ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; } + ObjToken& operator=(SubCls* obj) + { if (m_obj) m_obj->decrement(); m_obj = obj; m_obj->increment(); return *this; } + ObjToken& operator=(const ObjToken& other) + { if (m_obj) m_obj->decrement(); m_obj = other.m_obj; m_obj->increment(); return *this; } + ObjToken& operator=(ObjToken&& other) + { if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; } + ~ObjToken() { if (m_obj) m_obj->decrement(); } + SubCls* get() const { return m_obj; } + SubCls* operator->() const { return m_obj; } + SubCls& operator*() const { return *m_obj; } + template T* cast() const { return static_cast(m_obj); } + operator bool() const { return m_obj != nullptr; } +}; + +} + +#endif // BOOOBJECT_HPP diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index 8e1b21e..bcdf1b2 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -8,6 +8,7 @@ namespace boo { +class BaseGraphicsData; class GLDataFactory : public IGraphicsDataFactory { @@ -16,40 +17,44 @@ public: { friend class GLDataFactoryImpl; GLDataFactory& m_parent; - Context(GLDataFactory& parent) : m_parent(parent) {} + ObjToken m_data; + Context(GLDataFactory& parent); + ~Context(); public: - Platform platform() const {return Platform::OpenGL;} - const SystemChar* platformName() const {return _S("OpenGL");} + Platform platform() const { return Platform::OpenGL; } + const SystemChar* platformName() const { return _S("OpenGL"); } - IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); - IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count); + ObjToken newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); + ObjToken newDynamicBuffer(BufferUse use, size_t stride, size_t count); - ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, - TextureClampMode clampMode, const void* data, size_t sz); - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, - TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz); - ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); - ITextureR* newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, - size_t colorBindingCount, size_t depthBindingCount); + ObjToken newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + TextureClampMode clampMode, const void* data, size_t sz); + ObjToken newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz); + ObjToken newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); + ObjToken newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, + size_t colorBindingCount, size_t depthBindingCount); - bool bindingNeedsVertexFormat() const {return true;} - IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, - size_t baseVert = 0, size_t baseInst = 0); + bool bindingNeedsVertexFormat() const { return true; } + ObjToken newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, + size_t baseVert = 0, size_t baseInst = 0); - IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, - size_t texCount, const char** texNames, - size_t uniformBlockCount, const char** uniformBlockNames, - BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, bool colorWrite, - bool alphaWrite, CullMode culling); + ObjToken newShaderPipeline(const char* vertSource, const char* fragSource, + size_t texCount, const char** texNames, + size_t uniformBlockCount, const char** uniformBlockNames, + BlendFactor srcFac, BlendFactor dstFac, Primitive prim, + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling); - IShaderDataBinding* - newShaderDataBinding(IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, - size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, + ObjToken + newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* 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 df5495b..26bff5c 100644 --- a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp +++ b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp @@ -16,12 +16,12 @@ struct IGraphicsCommandQueue virtual Platform platform() const=0; virtual const SystemChar* platformName() const=0; - virtual void setShaderDataBinding(IShaderDataBinding* binding)=0; - virtual void setRenderTarget(ITextureR* target)=0; + virtual void setShaderDataBinding(const ObjToken& binding)=0; + virtual void setRenderTarget(const ObjToken& target)=0; virtual void setViewport(const SWindowRect& rect, float znear=0.f, float zfar=1.f)=0; virtual void setScissor(const SWindowRect& rect)=0; - virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0; + virtual void resizeRenderTexture(const ObjToken& tex, size_t width, size_t height)=0; virtual void schedulePostFrameHandler(std::function&& func)=0; virtual void setClearColor(const float rgba[4])=0; @@ -32,9 +32,9 @@ 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, + virtual void resolveBindTexture(const ObjToken& texture, const SWindowRect& rect, bool tlOrigin, int bindIdx, bool color, bool depth)=0; - virtual void resolveDisplay(ITextureR* source)=0; + virtual void resolveDisplay(const ObjToken& source)=0; virtual void execute()=0; virtual void stopRenderer()=0; diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 21f9416..780a576 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -6,47 +6,12 @@ #include #include "boo/System.hpp" #include "boo/ThreadLocalPtr.hpp" +#include "boo/BooObject.hpp" 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(IGraphicsData* parent, bool dynamic) - : m_parentData(parent), m_dynamic(dynamic) {} - virtual ~IGraphicsBuffer() = default; -}; - -/** Static resource buffer for verts, indices, uniform constants */ -struct IGraphicsBufferS : IGraphicsBuffer -{ -protected: - IGraphicsBufferS(IGraphicsData* parent) : IGraphicsBuffer(parent, false) {} -}; - -/** Dynamic resource buffer for verts, indices, uniform constants */ -struct IGraphicsBufferD : IGraphicsBuffer -{ - virtual void load(const void* data, size_t sz)=0; - virtual void* map(size_t sz)=0; - virtual void unmap()=0; -protected: - IGraphicsBufferD(IGraphicsData* parent) : IGraphicsBuffer(parent, true) {} -}; - /** Supported buffer uses */ enum class BufferUse { @@ -56,6 +21,33 @@ enum class BufferUse Uniform }; +/** Typeless graphics buffer */ +struct IGraphicsBuffer : IObj +{ + bool dynamic() const { return m_dynamic; } +protected: + bool m_dynamic; + explicit IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {} +}; + +/** Static resource buffer for verts, indices, uniform constants */ +struct IGraphicsBufferS : IGraphicsBuffer +{ +protected: + IGraphicsBufferS() : IGraphicsBuffer(false) {} +}; + +/** Dynamic resource buffer for verts, indices, uniform constants */ +struct IGraphicsBufferD : IGraphicsBuffer +{ + virtual void load(const void* data, size_t sz)=0; + virtual void* map(size_t sz)=0; + virtual void unmap()=0; +protected: + IGraphicsBufferD() : IGraphicsBuffer(true) {} +}; + +/** Texture access types */ enum class TextureType { Static, @@ -64,48 +56,6 @@ enum class TextureType Render }; -struct ITexture -{ - TextureType type() const {return m_type;} - IGraphicsData* m_parentData; -protected: - TextureType m_type; - ITexture(IGraphicsData* parent, TextureType type) - : m_parentData(parent), m_type(type) {} - virtual ~ITexture() {} -}; - -/** Static resource buffer for textures */ -struct ITextureS : ITexture -{ -protected: - ITextureS(IGraphicsData* parent) : ITexture(parent, TextureType::Static) {} -}; - -/** Static-array resource buffer for array textures */ -struct ITextureSA : ITexture -{ -protected: - ITextureSA(IGraphicsData* parent) : ITexture(parent, TextureType::StaticArray) {} -}; - -/** Dynamic resource buffer for textures */ -struct ITextureD : ITexture -{ - virtual void load(const void* data, size_t sz)=0; - virtual void* map(size_t sz)=0; - virtual void unmap()=0; -protected: - ITextureD(IGraphicsData* parent) : ITexture(parent, TextureType::Dynamic) {} -}; - -/** Resource buffer for render-target textures */ -struct ITextureR : ITexture -{ -protected: - ITextureR(IGraphicsData* parent) : ITexture(parent, TextureType::Render) {} -}; - /** Supported texture formats */ enum class TextureFormat { @@ -115,21 +65,57 @@ enum class TextureFormat PVRTC4 }; +/** Supported texture clamp modes */ enum class TextureClampMode { Repeat, ClampToWhite }; +/** Typeless texture */ +struct ITexture : IObj +{ + TextureType type() const { return m_type; } +protected: + TextureType m_type; + explicit ITexture(TextureType type) : m_type(type) {} +}; + +/** Static resource buffer for textures */ +struct ITextureS : ITexture +{ +protected: + ITextureS() : ITexture(TextureType::Static) {} +}; + +/** Static-array resource buffer for array textures */ +struct ITextureSA : ITexture +{ +protected: + ITextureSA() : ITexture(TextureType::StaticArray) {} +}; + +/** Dynamic resource buffer for textures */ +struct ITextureD : ITexture +{ + virtual void load(const void* data, size_t sz)=0; + virtual void* map(size_t sz)=0; + virtual void unmap()=0; +protected: + ITextureD() : ITexture(TextureType::Dynamic) {} +}; + +/** Resource buffer for render-target textures */ +struct ITextureR : ITexture +{ +protected: + ITextureR() : ITexture(TextureType::Render) {} +}; + /** 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 -{ - IGraphicsData* m_parentData; -protected: - IVertexFormat(IGraphicsData* parent) : m_parentData(parent) {} -}; +struct IVertexFormat : IObj {}; /** Types of vertex attributes */ enum class VertexSemantic @@ -164,17 +150,12 @@ struct VertexElementDescriptor /** Opaque token for referencing a complete graphics pipeline state necessary * to rasterize geometry (shaders and blending modes mainly) */ -struct IShaderPipeline -{ - IGraphicsData* m_parentData; -protected: - IShaderPipeline(IGraphicsData* parent) : m_parentData(parent) {} -}; +struct IShaderPipeline : IObj {}; /** Opaque token serving as indirection table for shader resources * and IShaderPipeline reference. Each renderable surface-material holds one * as a reference */ -struct IShaderDataBinding {}; +struct IShaderDataBinding : IObj {}; /** Used wherever distinction of pipeline stages is needed */ enum class PipelineStage @@ -252,44 +233,48 @@ struct IGraphicsDataFactory virtual Platform platform() const=0; virtual const SystemChar* platformName() const=0; - virtual IGraphicsBufferS* + virtual ObjToken newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0; - virtual IGraphicsBufferD* + virtual ObjToken newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0; - virtual ITextureS* + virtual ObjToken newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz)=0; - virtual ITextureSA* + virtual ObjToken newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz)=0; - virtual ITextureD* + virtual ObjToken newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode)=0; - virtual ITextureR* + virtual ObjToken newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, size_t colorBindingCount, size_t depthBindingCount)=0; virtual bool bindingNeedsVertexFormat() const=0; - virtual IVertexFormat* + virtual ObjToken newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert = 0, size_t baseInst = 0)=0; - virtual IShaderDataBinding* - newShaderDataBinding(IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, - size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, + virtual ObjToken + newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* 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, + ObjToken + newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, const PipelineStage* ubufStages, + size_t texCount, const ObjToken* texs, const int* texBindIdx, const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0) { @@ -300,130 +285,13 @@ struct IGraphicsDataFactory } }; - virtual GraphicsDataToken commitTransaction(const std::function&)=0; - virtual GraphicsBufferPoolToken newBufferPool()=0; + virtual void commitTransaction(const std::function&)=0; - virtual void destroyAllData()=0; -private: - friend class GraphicsDataToken; - virtual void destroyData(IGraphicsData*)=0; - - friend class GraphicsBufferPoolToken; - virtual void destroyPool(IGraphicsBufferPool*)=0; - virtual IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use, - size_t stride, size_t count)=0; - virtual void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)=0; + virtual ObjToken newPoolBuffer(BufferUse use, size_t stride, size_t count)=0; }; -using FactoryCommitFunc = std::function; - -/** Ownership token for maintaining lifetime of factory-created resources. - * Deletion of this token triggers mass-deallocation of the factory's - * IGraphicsData (please don't delete and draw contained resources in the same frame). */ -class GraphicsDataToken -{ - friend class GLDataFactoryImpl; - friend class D3D12DataFactory; - friend class D3D11DataFactory; - friend class MetalDataFactoryImpl; - friend class VulkanDataFactoryImpl; - IGraphicsDataFactory* m_factory = nullptr; - IGraphicsData* m_data = nullptr; - GraphicsDataToken(IGraphicsDataFactory* factory, IGraphicsData* data) - : m_factory(factory), m_data(data) {} -public: - void doDestroy() - { - if (m_factory && m_data) - { - m_factory->destroyData(m_data); - m_factory = nullptr; - m_data = nullptr; - } - } - GraphicsDataToken() = default; - GraphicsDataToken(const GraphicsDataToken& other) = delete; - GraphicsDataToken(GraphicsDataToken&& other) - { - m_factory = other.m_factory; - other.m_factory = nullptr; - m_data = other.m_data; - other.m_data = nullptr; - } - GraphicsDataToken& operator=(const GraphicsDataToken& other) = delete; - GraphicsDataToken& operator=(GraphicsDataToken&& other) - { - doDestroy(); - m_factory = other.m_factory; - other.m_factory = nullptr; - m_data = other.m_data; - other.m_data = nullptr; - return *this; - } - ~GraphicsDataToken() {doDestroy();} - operator bool() const {return m_factory && m_data;} -}; - -/** Ownership token for maintaining lifetimes of an appendable list of dynamic buffers. - * Deletion of this token triggers mass-deallocation of the IGraphicsBufferPool - * (please don't delete and draw contained resources in the same frame). */ -class GraphicsBufferPoolToken -{ - friend class GLDataFactoryImpl; - friend class D3D12DataFactory; - friend class D3D11DataFactory; - friend class MetalDataFactoryImpl; - friend class VulkanDataFactoryImpl; - IGraphicsDataFactory* m_factory = nullptr; - IGraphicsBufferPool* m_pool = nullptr; - GraphicsBufferPoolToken(IGraphicsDataFactory* factory, IGraphicsBufferPool* pool) - : m_factory(factory), m_pool(pool) {} -public: - void doDestroy() - { - if (m_factory && m_pool) - { - m_factory->destroyPool(m_pool); - m_factory = nullptr; - m_pool = nullptr; - } - } - GraphicsBufferPoolToken() = default; - GraphicsBufferPoolToken(const GraphicsBufferPoolToken& other) = delete; - GraphicsBufferPoolToken(GraphicsBufferPoolToken&& other) - { - m_factory = other.m_factory; - other.m_factory = nullptr; - m_pool = other.m_pool; - other.m_pool = nullptr; - } - GraphicsBufferPoolToken& operator=(const GraphicsBufferPoolToken& other) = delete; - GraphicsBufferPoolToken& operator=(GraphicsBufferPoolToken&& other) - { - doDestroy(); - m_factory = other.m_factory; - other.m_factory = nullptr; - m_pool = other.m_pool; - other.m_pool = nullptr; - return *this; - } - ~GraphicsBufferPoolToken() {doDestroy();} - operator bool() const {return m_factory && m_pool;} - - IGraphicsBufferD* newPoolBuffer(BufferUse use, - size_t stride, size_t count) - { - if (m_factory) - return m_factory->newPoolBuffer(m_pool, use, stride, count); - return nullptr; - } - - void deletePoolBuffer(IGraphicsBufferD* buf) - { - if (m_factory) - m_factory->deletePoolBuffer(m_pool, buf); - } -}; +using GraphicsDataFactoryContext = IGraphicsDataFactory::Context; +using FactoryCommitFunc = std::function; } diff --git a/include/boo/graphicsdev/Metal.hpp b/include/boo/graphicsdev/Metal.hpp index ecc2c81..c5a3a6b 100644 --- a/include/boo/graphicsdev/Metal.hpp +++ b/include/boo/graphicsdev/Metal.hpp @@ -19,37 +19,41 @@ public: MetalDataFactory& m_parent; Context(MetalDataFactory& parent) : m_parent(parent) {} public: - Platform platform() const {return Platform::Metal;} - const char* platformName() const {return "Metal";} + Platform platform() const { return Platform::Metal; } + const SystemChar* platformName() const { return _S("Metal"); } - IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); - IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count); + ObjToken newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); + ObjToken newDynamicBuffer(BufferUse use, size_t stride, size_t count); - ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, - TextureClampMode clampMode, const void* data, size_t sz); - ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, - TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz); - ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); - ITextureR* newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, - size_t colorBindCount, size_t depthBindCount); + ObjToken newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, + TextureClampMode clampMode, const void* data, size_t sz); + ObjToken newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, + TextureFormat fmt, TextureClampMode clampMode, const void* data, + size_t sz); + ObjToken newDynamicTexture(size_t width, size_t height, TextureFormat fmt, + TextureClampMode clampMode); + ObjToken newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, + size_t colorBindCount, size_t depthBindCount); - bool bindingNeedsVertexFormat() const {return false;} - IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, - size_t baseVert = 0, size_t baseInst = 0); + bool bindingNeedsVertexFormat() const { return false; } + ObjToken newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, + size_t baseVert = 0, size_t baseInst = 0); - IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, - IVertexFormat* vtxFmt, unsigned targetSamples, - BlendFactor srcFac, BlendFactor dstFac, Primitive prim, - ZTest depthTest, bool depthWrite, bool colorWrite, - bool alphaWrite, CullMode culling); + ObjToken newShaderPipeline(const char* vertSource, const char* fragSource, + IVertexFormat* vtxFmt, unsigned targetSamples, + BlendFactor srcFac, BlendFactor dstFac, Primitive prim, + ZTest depthTest, bool depthWrite, bool colorWrite, + bool alphaWrite, CullMode culling); - IShaderDataBinding* - newShaderDataBinding(IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, - size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, + ObjToken + newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* texs, const int* texBindIdxs, const bool* depthBind, size_t baseVert = 0, size_t baseInst = 0); }; diff --git a/lib/graphicsdev/Common.hpp b/lib/graphicsdev/Common.hpp index 67d6d2b..d31c5a2 100644 --- a/lib/graphicsdev/Common.hpp +++ b/lib/graphicsdev/Common.hpp @@ -6,63 +6,219 @@ #include #include +#include #include "boo/graphicsdev/IGraphicsDataFactory.hpp" namespace boo { -class IGraphicsDataPriv : public IGraphicsData +struct BaseGraphicsData; +struct BaseGraphicsPool; + +template +struct GraphicsDataNode; + +/** Inherited by data factory implementations to track the head data and pool nodes */ +struct GraphicsDataFactoryHead { - std::atomic_int m_refCount = {1}; -public: - void increment() { m_refCount++; } - void decrement() - { - if (m_refCount.fetch_sub(1) == 1) - delete this; - } + std::mutex m_dataMutex; + BaseGraphicsData* m_dataHead = nullptr; + BaseGraphicsPool* m_poolHead = nullptr; }; -class IShaderDataBindingPriv : public IShaderDataBinding +/** Private generalized data container class. + * Keeps head pointers to all graphics objects by type + */ +struct BaseGraphicsData : IObj { - IGraphicsDataPriv* m_parent; - std::vector m_depDatas; + GraphicsDataFactoryHead& m_head; + BaseGraphicsData* m_next; + BaseGraphicsData* m_prev = nullptr; + GraphicsDataNode* m_SPs = nullptr; + GraphicsDataNode* m_SBinds = nullptr; + GraphicsDataNode* m_SBufs = nullptr; + GraphicsDataNode* m_DBufs = nullptr; + GraphicsDataNode* m_STexs = nullptr; + GraphicsDataNode* m_SATexs = nullptr; + GraphicsDataNode* m_DTexs = nullptr; + GraphicsDataNode* m_RTexs = nullptr; + GraphicsDataNode* m_VFmts = nullptr; + template GraphicsDataNode*& getHead(); -public: - IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {} - class Token + explicit BaseGraphicsData(GraphicsDataFactoryHead& head) + : m_head(head) { - IGraphicsDataPriv* m_data = nullptr; - public: - Token() = default; - Token(const IShaderDataBindingPriv* p) - : 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 lock() const { return Token(this); } - ~IShaderDataBindingPriv() - { - for (IGraphicsDataPriv* dep : m_depDatas) - dep->decrement(); + std::lock_guard lk(m_head.m_dataMutex); + m_next = head.m_dataHead; + head.m_dataHead = this; } - -protected: - void addDepData(IGraphicsData* data) + ~BaseGraphicsData() { - IGraphicsDataPriv* d = static_cast(data); - if (d != m_parent) + std::lock_guard lk(m_head.m_dataMutex); + if (m_prev) { - m_depDatas.push_back(d); - d->increment(); + if (m_next) + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + else + { + if (m_next) + m_next->m_prev = m_head.m_dataHead; + m_head.m_dataHead = m_next; } } + + class iterator + { + BaseGraphicsData* m_node; + public: + using value_type = BaseGraphicsData; + using pointer = BaseGraphicsData*; + using reference = BaseGraphicsData&; + using iterator_category = std::bidirectional_iterator_tag; + + explicit iterator(BaseGraphicsData* node) : m_node(node) {} + BaseGraphicsData& operator*() const { return *m_node; } + bool operator!=(const iterator& other) const { return m_node != other.m_node; } + iterator& operator++() { m_node = m_node->m_next; return *this; } + iterator& operator--() { m_node = m_node->m_prev; return *this; } + }; + + iterator begin() { return iterator(this); } + iterator end() { return iterator(nullptr); } +}; + +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_SPs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_SBinds; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_SBufs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_DBufs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_STexs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_SATexs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_DTexs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_RTexs; } +template <> GraphicsDataNode*& +BaseGraphicsData::getHead() { return m_VFmts; } + +/** Private generalized pool container class. + * Keeps head pointer to exactly one dynamic buffer while otherwise conforming to IGraphicsData + */ +struct BaseGraphicsPool : IObj +{ + GraphicsDataFactoryHead& m_head; + BaseGraphicsPool* m_next; + BaseGraphicsPool* m_prev = nullptr; + GraphicsDataNode* m_DBufs = nullptr; + template GraphicsDataNode*& getHead(); + + explicit BaseGraphicsPool(GraphicsDataFactoryHead& head) + : m_head(head) + { + std::lock_guard lk(m_head.m_dataMutex); + m_next = head.m_poolHead; + head.m_poolHead = this; + } + ~BaseGraphicsPool() + { + std::lock_guard lk(m_head.m_dataMutex); + if (m_prev) + { + if (m_next) + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + else + { + if (m_next) + m_next->m_prev = m_head.m_poolHead; + m_head.m_poolHead = m_next; + } + } + + class iterator + { + BaseGraphicsPool* m_node; + public: + using value_type = BaseGraphicsPool; + using pointer = BaseGraphicsPool*; + using reference = BaseGraphicsPool&; + using iterator_category = std::bidirectional_iterator_tag; + + explicit iterator(BaseGraphicsPool* node) : m_node(node) {} + BaseGraphicsPool& operator*() const { return *m_node; } + bool operator!=(const iterator& other) const { return m_node != other.m_node; } + iterator& operator++() { m_node = m_node->m_next; return *this; } + iterator& operator--() { m_node = m_node->m_prev; return *this; } + }; + + iterator begin() { return iterator(this); } + iterator end() { return iterator(nullptr); } +}; + +template <> GraphicsDataNode*& +BaseGraphicsPool::getHead() { return m_DBufs; } + +/** Private generalised graphics object node. + * Keeps a strong reference to the data pool that it's a member of; + * as well as doubly-linked pointers to same-type sibling objects + */ +template +struct GraphicsDataNode : NodeCls +{ + ObjToken m_data; + GraphicsDataNode* m_next; + GraphicsDataNode* m_prev = nullptr; + + explicit GraphicsDataNode(const ObjToken& data) + : m_data(data) + { + std::lock_guard lk(m_data->m_head.m_dataMutex); + m_next = data->template getHead(); + data->template getHead() = this; + } + ~GraphicsDataNode() + { + std::lock_guard lk(m_data->m_head.m_dataMutex); + if (m_prev) + { + if (m_next) + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + else + { + if (m_next) + m_next->m_prev = m_data->template getHead(); + m_data->template getHead() = m_next; + } + } + + class iterator + { + GraphicsDataNode* m_node; + public: + using value_type = NodeCls; + using pointer = NodeCls*; + using reference = NodeCls&; + using iterator_category = std::bidirectional_iterator_tag; + + explicit iterator(GraphicsDataNode* node) : m_node(node) {} + NodeCls& operator*() const { return *m_node; } + bool operator!=(const iterator& other) const { return m_node != other.m_node; } + iterator& operator++() { m_node = m_node->m_next; return *this; } + iterator& operator--() { m_node = m_node->m_prev; return *this; } + }; + + iterator begin() { return iterator(this); } + iterator end() { return iterator(nullptr); } }; template diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 866dafe..5810352 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -1,16 +1,11 @@ #include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/glew.h" -#include "boo/IGraphicsContext.hpp" #include "Common.hpp" -#include #include -#include #include #include #include #include -#include -#include #include "xxhash.h" #include "logvisor/logvisor.hpp" @@ -31,68 +26,21 @@ struct GLShareableShader : IShareableShader m_deferredData; - std::unordered_set m_committedData; - std::unordered_set m_committedPools; - std::mutex m_committedMutex; std::unordered_map> m_sharedShaders; - void destroyData(IGraphicsData*); - void destroyAllData(); - void destroyPool(IGraphicsBufferPool*); - IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use, - size_t stride, size_t count); - void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf); public: GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples); - ~GLDataFactoryImpl() {destroyAllData();} - Platform platform() const {return Platform::OpenGL;} - const SystemChar* platformName() const {return _S("OpenGL");} - - GraphicsDataToken commitTransaction(const FactoryCommitFunc&); - GraphicsBufferPoolToken newBufferPool(); - - void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) - { - m_sharedShaders.erase(srcKey); - } -}; - -ThreadLocalPtr GLDataFactoryImpl::m_deferredData; -struct GLData : IGraphicsDataPriv -{ - int m_deadCounter = 0; - std::vector> m_SPs; - std::vector> m_SBinds; - std::vector> m_SBufs; - std::vector> m_DBufs; - std::vector> m_STexs; - std::vector> m_SATexs; - std::vector> m_DTexs; - std::vector> m_RTexs; - std::vector> m_VFmts; -}; - -struct GLPoolItem : IGraphicsDataPriv -{ - std::unique_ptr m_buf; -}; - -struct GLPool : IGraphicsBufferPool -{ - int m_deadCounter = 0; - std::unordered_set m_items; - ~GLPool() - { - for (auto& item : m_items) - item->decrement(); - } + Platform platform() const { return Platform::OpenGL; } + const SystemChar* platformName() const { return _S("OpenGL"); } + void commitTransaction(const FactoryCommitFunc&); + ObjToken newPoolBuffer(BufferUse use, size_t stride, size_t count); + void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); } }; static const GLenum USE_TABLE[] = @@ -103,14 +51,14 @@ static const GLenum USE_TABLE[] = GL_UNIFORM_BUFFER }; -class GLGraphicsBufferS : public IGraphicsBufferS +class GLGraphicsBufferS : public GraphicsDataNode { friend class GLDataFactory; friend struct GLCommandQueue; GLuint m_buf; GLenum m_target; - GLGraphicsBufferS(IGraphicsData* parent, BufferUse use, const void* data, size_t sz) - : IGraphicsBufferS(parent) + GLGraphicsBufferS(const ObjToken& parent, BufferUse use, const void* data, size_t sz) + : GraphicsDataNode(parent) { Log.report(logvisor::Info, "Create static buffer %p\n", this); m_target = USE_TABLE[int(use)]; @@ -131,7 +79,8 @@ public: {glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_buf, off, size);} }; -class GLGraphicsBufferD : public IGraphicsBufferD +template +class GLGraphicsBufferD : public GraphicsDataNode { friend class GLDataFactory; friend class GLDataFactoryImpl; @@ -141,8 +90,8 @@ class GLGraphicsBufferD : public IGraphicsBufferD std::unique_ptr m_cpuBuf; size_t m_cpuSz = 0; int m_validMask = 0; - GLGraphicsBufferD(IGraphicsData* parent, BufferUse use, size_t sz) - : boo::IGraphicsBufferD(parent), + GLGraphicsBufferD(const ObjToken& parent, BufferUse use, size_t sz) + : GraphicsDataNode(parent), m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) { Log.report(logvisor::Info, "Create dynamic buffer %p\n", this); @@ -167,13 +116,10 @@ public: void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b); }; -IGraphicsBufferS* +ObjToken GLDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); - GLGraphicsBufferS* retval = new GLGraphicsBufferS(d, use, data, stride * count); - d->m_SBufs.emplace_back(retval); - return retval; + return {new GLGraphicsBufferS(m_data, use, data, stride * count)}; } static void SetClampMode(GLenum target, TextureClampMode clampMode) @@ -199,13 +145,13 @@ static void SetClampMode(GLenum target, TextureClampMode clampMode) } } -class GLTextureS : public ITextureS +class GLTextureS : public GraphicsDataNode { friend class GLDataFactory; GLuint m_tex; - GLTextureS(GLData* parent, size_t width, size_t height, size_t mips, + GLTextureS(const ObjToken& parent, size_t width, size_t height, size_t mips, TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz) - : ITextureS(parent) + : GraphicsDataNode(parent) { const uint8_t* dataIt = static_cast(data); glGenTextures(1, &m_tex); @@ -280,13 +226,13 @@ public: } }; -class GLTextureSA : public ITextureSA +class GLTextureSA : public GraphicsDataNode { friend class GLDataFactory; GLuint m_tex; - GLTextureSA(GLData* parent, size_t width, size_t height, size_t layers, size_t mips, + GLTextureSA(const ObjToken& parent, size_t width, size_t height, size_t layers, size_t mips, TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz) - : ITextureSA(parent) + : GraphicsDataNode(parent) { const uint8_t* dataIt = static_cast(data); glGenTextures(1, &m_tex); @@ -337,7 +283,7 @@ public: } }; -class GLTextureD : public ITextureD +class GLTextureD : public GraphicsDataNode { friend class GLDataFactory; friend struct GLCommandQueue; @@ -348,7 +294,7 @@ class GLTextureD : public ITextureD size_t m_width = 0; size_t m_height = 0; int m_validMask = 0; - GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); + GLTextureD(const ObjToken& parent, size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); void update(int b); public: ~GLTextureD(); @@ -362,7 +308,7 @@ public: #define MAX_BIND_TEXS 4 -class GLTextureR : public ITextureR +class GLTextureR : public GraphicsDataNode { friend class GLDataFactory; friend struct GLCommandQueue; @@ -374,7 +320,7 @@ class GLTextureR : public ITextureR size_t m_height = 0; size_t m_samples = 0; GLenum m_target; - GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, + GLTextureR(const ObjToken& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount); public: ~GLTextureR(); @@ -429,27 +375,22 @@ public: } }; -ITextureS* +ObjToken GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); - GLTextureS* retval = new GLTextureS(d, width, height, mips, fmt, clampMode, data, sz); - d->m_STexs.emplace_back(retval); - return retval; + return {new GLTextureS(m_data, width, height, mips, fmt, clampMode, data, sz)}; } -ITextureSA* +ObjToken GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, - TextureFormat fmt, TextureClampMode clampMode, const void *data, size_t sz) + TextureFormat fmt, TextureClampMode clampMode, + const void *data, size_t sz) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); - GLTextureSA* retval = new GLTextureSA(d, width, height, layers, mips, fmt, clampMode, data, sz); - d->m_SATexs.emplace_back(retval); - return retval; + return {new GLTextureSA(m_data, width, height, layers, mips, fmt, clampMode, data, sz)}; } -class GLShaderPipeline : public IShaderPipeline +class GLShaderPipeline : public GraphicsDataNode { friend class GLDataFactory; friend struct GLCommandQueue; @@ -469,33 +410,10 @@ class GLShaderPipeline : public IShaderPipeline mutable std::vector m_uniLocs; mutable std::vector m_texNames; mutable std::vector m_blockNames; - GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {} + GLShaderPipeline(const ObjToken& parent) + : GraphicsDataNode(parent) {} public: ~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); } - GLShaderPipeline& operator=(const GLShaderPipeline&) = delete; - GLShaderPipeline(const GLShaderPipeline&) = delete; - GLShaderPipeline& operator=(GLShaderPipeline&& other) - { - m_vert = std::move(other.m_vert); - m_frag = std::move(other.m_frag); - m_prog = other.m_prog; - other.m_prog = 0; - m_sfactor = other.m_sfactor; - m_dfactor = other.m_dfactor; - 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_subtractBlend = other.m_subtractBlend; - m_culling = other.m_culling; - m_uniLocs = std::move(other.m_uniLocs); - m_texNames = std::move(other.m_texNames); - m_blockNames = std::move(other.m_blockNames); - return *this; - } - GLShaderPipeline(GLShaderPipeline&& other) - : IShaderPipeline(other.m_parentData) { *this = std::move(other); } GLuint bind() const { @@ -525,10 +443,9 @@ public: { GLint logLen; glGetProgramiv(m_prog, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetProgramInfoLog(m_prog, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to link shader program\n%s\n", log); - free(log); + std::unique_ptr log(new char[logLen]); + glGetProgramInfoLog(m_prog, logLen, nullptr, log.get()); + Log.report(logvisor::Error, "unable to link shader program\n%s\n", log.get()); return 0; } @@ -636,7 +553,7 @@ static const GLenum BLEND_FACTOR_TABLE[] = GL_ONE_MINUS_SRC1_COLOR }; -IShaderPipeline* GLDataFactory::Context::newShaderPipeline +ObjToken GLDataFactory::Context::newShaderPipeline (const char* vertSource, const char* fragSource, size_t texCount, const char** texNames, size_t uniformBlockCount, const char** uniformBlockNames, @@ -644,9 +561,9 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline ZTest depthTest, bool depthWrite, bool colorWrite, bool alphaWrite, CullMode culling) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); GLDataFactoryImpl& factory = static_cast(m_parent); - GLShaderPipeline shader(d); + ObjToken retval(new GLShaderPipeline(m_data)); + GLShaderPipeline& shader = *retval.cast(); XXH64_state_t hashState; uint64_t hashes[2]; @@ -669,7 +586,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline if (!sobj) { Log.report(logvisor::Error, "unable to create vert shader"); - return nullptr; + return {}; } glShaderSource(sobj, 1, &vertSource, nullptr); @@ -679,11 +596,10 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline { GLint logLen; glGetShaderiv(sobj, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetShaderInfoLog(sobj, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to compile vert source\n%s\n%s\n", log, vertSource); - free(log); - return nullptr; + std::unique_ptr log(new char[logLen]); + glGetShaderInfoLog(sobj, logLen, nullptr, log.get()); + Log.report(logvisor::Error, "unable to compile vert source\n%s\n%s\n", log.get(), vertSource); + return {}; } auto it = @@ -702,7 +618,7 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline if (!sobj) { Log.report(logvisor::Error, "unable to create frag shader"); - return nullptr; + return {}; } glShaderSource(sobj, 1, &fragSource, nullptr); @@ -712,11 +628,10 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline { GLint logLen; glGetShaderiv(sobj, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetShaderInfoLog(sobj, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to compile frag source\n%s\n%s\n", log, fragSource); - free(log); - return nullptr; + std::unique_ptr log(new char[logLen]); + glGetShaderInfoLog(sobj, logLen, nullptr, log.get()); + Log.report(logvisor::Error, "unable to compile frag source\n%s\n%s\n", log.get(), fragSource); + return {}; } auto it = @@ -753,59 +668,49 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline shader.m_culling = culling; shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)]; - GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); - d->m_SPs.emplace_back(retval); return retval; } -struct GLVertexFormat : IVertexFormat +struct GLVertexFormat : GraphicsDataNode { GLCommandQueue* m_q; GLuint m_vao[3] = {}; size_t m_elementCount; GLuint m_baseVert, m_baseInst; std::unique_ptr m_elements; - GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount, + GLVertexFormat(const ObjToken& 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 : GraphicsDataNode { - const GLShaderPipeline* m_pipeline; - const GLVertexFormat* m_vtxFormat; - size_t m_ubufCount; - std::unique_ptr m_ubufs; + ObjToken m_pipeline; + ObjToken m_vtxFormat; + std::vector> m_ubufs; std::vector> m_ubufOffs; - size_t m_texCount; struct BoundTex { - ITexture* tex; + ObjToken tex; int idx; bool depth; }; - std::unique_ptr m_texs; + std::vector m_texs; - GLShaderDataBinding(GLData* d, - IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - size_t ubufCount, IGraphicsBuffer** ubufs, + GLShaderDataBinding(const ObjToken& d, + const ObjToken& pipeline, + const ObjToken& vtxFormat, + size_t ubufCount, const ObjToken* ubufs, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* 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 BoundTex[texCount]) + : GraphicsDataNode(d), + m_pipeline(pipeline), + m_vtxFormat(vtxFormat) { - addDepData(m_pipeline->m_parentData); - addDepData(m_vtxFormat->m_parentData); if (ubufOffs && ubufSizes) { m_ubufOffs.reserve(ubufCount); @@ -818,38 +723,37 @@ struct GLShaderDataBinding : IShaderDataBindingPriv m_ubufOffs.emplace_back(ubufOffs[i], (ubufSizes[i] + 255) & ~255); } } + m_ubufs.reserve(ubufCount); for (size_t i=0 ; im_parentData); + m_ubufs.push_back(ubufs[i]); } + m_texs.reserve(texCount); for (size_t i=0 ; im_parentData); } } void bind(int b) const { - GLuint prog = m_pipeline->bind(); - m_vtxFormat->bind(b); + GLShaderPipeline& pipeline = *m_pipeline.cast(); + GLuint prog = pipeline.bind(); + m_vtxFormat.cast()->bind(b); if (m_ubufOffs.size()) { - for (size_t i=0 ; im_uniLocs.size() ; ++i) + for (size_t i=0 ; im_uniLocs[i]; + GLint loc = pipeline.m_uniLocs[i]; if (loc < 0) continue; - IGraphicsBuffer* ubuf = m_ubufs[i]; + IGraphicsBuffer* ubuf = m_ubufs[i].get(); const std::pair& offset = m_ubufOffs[i]; if (ubuf->dynamic()) - static_cast(ubuf)->bindUniformRange(i, offset.first, offset.second, b); + static_cast*>(ubuf)->bindUniformRange(i, offset.first, offset.second, b); else static_cast(ubuf)->bindUniformRange(i, offset.first, offset.second); glUniformBlockBinding(prog, loc, i); @@ -857,37 +761,37 @@ struct GLShaderDataBinding : IShaderDataBindingPriv } else { - for (size_t i=0 ; im_uniLocs.size() ; ++i) + for (size_t i=0 ; im_uniLocs[i]; + GLint loc = pipeline.m_uniLocs[i]; if (loc < 0) continue; - IGraphicsBuffer* ubuf = m_ubufs[i]; + IGraphicsBuffer* ubuf = m_ubufs[i].get(); if (ubuf->dynamic()) - static_cast(ubuf)->bindUniform(i, b); + static_cast*>(ubuf)->bindUniform(i, b); else static_cast(ubuf)->bindUniform(i); glUniformBlockBinding(prog, loc, i); } } - for (size_t i=0 ; itype()) { case TextureType::Dynamic: - static_cast(tex.tex)->bind(i, b); + tex.tex.cast()->bind(i, b); break; case TextureType::Static: - static_cast(tex.tex)->bind(i); + tex.tex.cast()->bind(i); break; case TextureType::StaticArray: - static_cast(tex.tex)->bind(i); + tex.tex.cast()->bind(i); break; case TextureType::Render: - static_cast(tex.tex)->bind(i, tex.idx, tex.depth); + tex.tex.cast()->bind(i, tex.idx, tex.depth); break; default: break; } @@ -896,111 +800,48 @@ struct GLShaderDataBinding : IShaderDataBindingPriv } }; -IShaderDataBinding* -GLDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, - size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, +ObjToken +GLDataFactory::Context::newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, + const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* 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, texBindIdx, depthBind); - GLDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval); - return retval; + return {new GLShaderDataBinding(m_data, pipeline, vtxFormat, ubufCount, ubufs, + ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind)}; } GLDataFactoryImpl::GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples) : m_parent(parent), m_drawSamples(drawSamples) {} +GLDataFactory::Context::Context(GLDataFactory& parent) +: m_parent(parent), m_data(new BaseGraphicsData(static_cast(parent))) +{} -GraphicsDataToken GLDataFactoryImpl::commitTransaction(const FactoryCommitFunc& trans) +GLDataFactory::Context::~Context() {} + +void GLDataFactoryImpl::commitTransaction(const FactoryCommitFunc& trans) { - if (m_deferredData.get()) - Log.report(logvisor::Fatal, "nested commitTransaction usage detected"); - m_deferredData.reset(new GLData()); - GLDataFactory::Context ctx(*this); if (!trans(ctx)) - { - delete m_deferredData.get(); - m_deferredData.reset(); - return GraphicsDataToken(this, nullptr); - } + return; - std::unique_lock lk(m_committedMutex); - GLData* retval = m_deferredData.get(); - m_deferredData.reset(); - m_committedData.insert(retval); - - lk.unlock(); /* 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(); - return GraphicsDataToken(this, retval); } -GraphicsBufferPoolToken GLDataFactoryImpl::newBufferPool() +ObjToken GLDataFactoryImpl::newPoolBuffer(BufferUse use, size_t stride, size_t count) { - std::unique_lock lk(m_committedMutex); - GLPool* retval = new GLPool; - m_committedPools.insert(retval); - return GraphicsBufferPoolToken(this, retval); -} - -void GLDataFactoryImpl::destroyData(IGraphicsData* d) -{ - std::unique_lock lk(m_committedMutex); - GLData* data = static_cast(d); - data->m_deadCounter = 3; - //m_committedData.erase(data); - //data->decrement(); -} - -void GLDataFactoryImpl::destroyAllData() -{ - std::unique_lock lk(m_committedMutex); - for (GLData* data : m_committedData) - data->decrement(); - for (GLPool* pool : m_committedPools) - delete pool; - m_committedData.clear(); - m_committedPools.clear(); -} - -void GLDataFactoryImpl::destroyPool(IGraphicsBufferPool* p) -{ - std::unique_lock lk(m_committedMutex); - GLPool* pool = static_cast(p); - pool->m_deadCounter = 3; - //m_committedPools.erase(pool); - //delete pool; -} - -IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, - size_t stride, size_t count) -{ - GLPool* pool = static_cast(p); - 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) -{ - GLPool* pool = static_cast(p); - auto search = pool->m_items.find(static_cast(buf->m_parentData)); - if (search != pool->m_items.end()) - { - (*search)->decrement(); - pool->m_items.erase(search); - } + ObjToken pool(new BaseGraphicsPool(*this)); + return {new GLGraphicsBufferD(pool, use, stride * count)}; } static const GLint SEMANTIC_COUNT_TABLE[] = @@ -1050,8 +891,8 @@ static const GLenum SEMANTIC_TYPE_TABLE[] = struct GLCommandQueue : IGraphicsCommandQueue { - Platform platform() const {return IGraphicsDataFactory::Platform::OpenGL;} - const SystemChar* platformName() const {return _S("OpenGL");} + Platform platform() const { return IGraphicsDataFactory::Platform::OpenGL; } + const SystemChar* platformName() const { return _S("OpenGL"); } IGraphicsContext* m_parent = nullptr; std::mutex m_mt; @@ -1080,9 +921,6 @@ struct GLCommandQueue : IGraphicsCommandQueue } m_op; union { - const IShaderDataBinding* binding; - const ITextureR* target; - const ITextureR* source; struct { SWindowRect rect; @@ -1097,8 +935,10 @@ struct GLCommandQueue : IGraphicsCommandQueue size_t instCount; }; }; - IShaderDataBindingPriv::Token resToken; - const ITextureR* resolveTex; + ObjToken binding; + ObjToken target; + ObjToken source; + ObjToken resolveTex; int bindIdx; bool resolveColor : 1; bool resolveDepth : 1; @@ -1109,14 +949,14 @@ struct GLCommandQueue : IGraphicsCommandQueue Command& operator=(Command&&) = default; }; std::vector m_cmdBufs[3]; - size_t m_fillBuf = 0; - size_t m_completeBuf = 0; - size_t m_drawBuf = 0; + int m_fillBuf = 0; + int m_completeBuf = 0; + int m_drawBuf = 0; bool m_running = true; struct RenderTextureResize { - GLTextureR* tex; + ObjToken tex; size_t width; size_t height; }; @@ -1125,10 +965,8 @@ struct GLCommandQueue : IGraphicsCommandQueue std::vector m_pendingResizes; std::vector> m_pendingPosts1; std::vector> m_pendingPosts2; - std::vector m_pendingFmtAdds; - //std::vector> m_pendingFmtDels; - std::vector m_pendingFboAdds; - //std::vector m_pendingFboDels; + std::vector> m_pendingFmtAdds; + std::vector> m_pendingFboAdds; static void ConfigureVertexFormat(GLVertexFormat* fmt) { @@ -1159,7 +997,7 @@ struct GLCommandQueue : IGraphicsCommandQueue { lastVBO = desc->vertBuffer; if (lastVBO->dynamic()) - static_cast(lastVBO)->bindVertex(b); + static_cast*>(lastVBO)->bindVertex(b); else static_cast(lastVBO)->bindVertex(); } @@ -1167,7 +1005,7 @@ struct GLCommandQueue : IGraphicsCommandQueue { lastEBO = desc->indexBuffer; if (lastEBO->dynamic()) - static_cast(lastEBO)->bindIndex(b); + static_cast*>(lastEBO)->bindIndex(b); else static_cast(lastEBO)->bindIndex(); } @@ -1226,41 +1064,25 @@ struct GLCommandQueue : IGraphicsCommandQueue if (self->m_pendingFboAdds.size()) { - for (GLTextureR* tex : self->m_pendingFboAdds) - ConfigureFBO(tex); + for (ObjToken& tex : self->m_pendingFboAdds) + ConfigureFBO(tex.cast()); self->m_pendingFboAdds.clear(); } if (self->m_pendingResizes.size()) { for (const RenderTextureResize& resize : self->m_pendingResizes) - resize.tex->resize(resize.width, resize.height); + resize.tex.cast()->resize(resize.width, resize.height); self->m_pendingResizes.clear(); } if (self->m_pendingFmtAdds.size()) { - for (GLVertexFormat* fmt : self->m_pendingFmtAdds) - if (fmt) ConfigureVertexFormat(fmt); + for (ObjToken& fmt : self->m_pendingFmtAdds) + if (fmt) ConfigureVertexFormat(fmt.cast()); self->m_pendingFmtAdds.clear(); } -#if 0 - if (self->m_pendingFmtDels.size()) - { - for (const auto& fmt : self->m_pendingFmtDels) - glDeleteVertexArrays(3, fmt.data()); - self->m_pendingFmtDels.clear(); - } - - if (self->m_pendingFboDels.size()) - { - for (GLuint fbo : self->m_pendingFboDels) - glDeleteFramebuffers(1, &fbo); - self->m_pendingFboDels.clear(); - } -#endif - if (self->m_pendingPosts2.size()) posts.swap(self->m_pendingPosts2); } @@ -1273,15 +1095,15 @@ struct GLCommandQueue : IGraphicsCommandQueue { case Command::Op::SetShaderDataBinding: { - const GLShaderDataBinding* binding = static_cast(cmd.binding); + const GLShaderDataBinding* binding = cmd.binding.cast(); binding->bind(self->m_drawBuf); curBinding = binding; - currentPrim = binding->m_pipeline->m_drawPrim; + currentPrim = binding->m_pipeline.cast()->m_drawPrim; break; } case Command::Op::SetRenderTarget: { - const GLTextureR* tex = static_cast(cmd.target); + const GLTextureR* tex = cmd.target.cast(); if (!tex) glBindFramebuffer(GL_FRAMEBUFFER, 0); else @@ -1329,7 +1151,7 @@ struct GLCommandQueue : IGraphicsCommandQueue break; case Command::Op::ResolveBindTexture: { - const GLTextureR* tex = static_cast(cmd.resolveTex); + const GLTextureR* tex = cmd.resolveTex.cast(); GLenum target = (tex->m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); glActiveTexture(GL_TEXTURE9); @@ -1351,8 +1173,7 @@ struct GLCommandQueue : IGraphicsCommandQueue } case Command::Op::Present: { - const GLTextureR* tex = static_cast(cmd.source); - if (tex) + if (const GLTextureR* tex = cmd.source.cast()) { glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); @@ -1365,34 +1186,9 @@ struct GLCommandQueue : IGraphicsCommandQueue default: break; } } - cmds.clear(); for (auto& p : posts) p(); - - GLDataFactoryImpl* gfxF = static_cast(self->m_parent->getDataFactory()); - std::unique_lock datalk(gfxF->m_committedMutex); - for (auto it = gfxF->m_committedData.begin() ; it != gfxF->m_committedData.end() ;) - { - GLData* d = *it; - if (d->m_deadCounter && --d->m_deadCounter == 0) - { - d->decrement(); - it = gfxF->m_committedData.erase(it); - continue; - } - ++it; - } - for (auto it = gfxF->m_committedPools.begin() ; it != gfxF->m_committedPools.end() ;) - { - GLPool* p = *it; - if (p->m_deadCounter && --p->m_deadCounter == 0) - { - delete p; - it = gfxF->m_committedPools.erase(it); - continue; - } - ++it; - } + cmds.clear(); } } @@ -1423,15 +1219,14 @@ struct GLCommandQueue : IGraphicsCommandQueue stopRenderer(); } - void setShaderDataBinding(IShaderDataBinding* binding) + void setShaderDataBinding(const ObjToken& binding) { std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::SetShaderDataBinding); cmds.back().binding = binding; - cmds.back().resToken = static_cast(binding)->lock(); } - void setRenderTarget(ITextureR* target) + void setRenderTarget(const ObjToken& target) { std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::SetRenderTarget); @@ -1454,10 +1249,10 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().viewport.rect = rect; } - void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) + void resizeRenderTexture(const ObjToken& tex, size_t width, size_t height) { std::unique_lock lk(m_mt); - GLTextureR* texgl = static_cast(tex); + GLTextureR* texgl = tex.cast(); m_pendingResizes.push_back({texgl, width, height}); } @@ -1521,10 +1316,10 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().instCount = instCount; } - void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, + void resolveBindTexture(const ObjToken& texture, const SWindowRect& rect, bool tlOrigin, int bindIdx, bool color, bool depth) { - GLTextureR* tex = static_cast(texture); + GLTextureR* tex = texture.cast(); std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::ResolveBindTexture); cmds.back().resolveTex = texture; @@ -1542,20 +1337,20 @@ struct GLCommandQueue : IGraphicsCommandQueue targetRect.size[1] = intersectRect.size[1]; } - void resolveDisplay(ITextureR* source) + void resolveDisplay(const ObjToken& source) { std::vector& cmds = m_cmdBufs[m_fillBuf]; cmds.emplace_back(Command::Op::Present); cmds.back().source = source; } - void addVertexFormat(GLVertexFormat* fmt) + void addVertexFormat(const ObjToken& fmt) { std::unique_lock lk(m_mt); m_pendingFmtAdds.push_back(fmt); } - void delVertexFormat(GLVertexFormat* fmt) + void delVertexFormat(const ObjToken& fmt) { #if 0 std::unique_lock lk(m_mt); @@ -1573,26 +1368,26 @@ struct GLCommandQueue : IGraphicsCommandQueue glDeleteVertexArrays(3, fmt->m_vao); } - void addFBO(GLTextureR* tex) + void addFBO(const ObjToken& tex) { std::unique_lock lk(m_mt); m_pendingFboAdds.push_back(tex); } - void delFBO(GLTextureR* tex) + void delFBO(const ObjToken& tex) { #if 0 std::unique_lock lk(m_mt); m_pendingFboDels.push_back(tex->m_fbo); #endif - glDeleteFramebuffers(1, &tex->m_fbo); + glDeleteFramebuffers(1, &tex.cast()->m_fbo); } void execute() { std::unique_lock lk(m_mt); m_completeBuf = m_fillBuf; - for (size_t i=0 ; i<3 ; ++i) + for (int i=0 ; i<3 ; ++i) { if (i == m_completeBuf || i == m_drawBuf) continue; @@ -1602,18 +1397,27 @@ struct GLCommandQueue : IGraphicsCommandQueue /* Update dynamic data here */ GLDataFactoryImpl* gfxF = static_cast(m_parent->getDataFactory()); - std::unique_lock datalk(gfxF->m_committedMutex); - for (GLData* d : gfxF->m_committedData) + std::unique_lock datalk(gfxF->m_dataMutex); + if (gfxF->m_dataHead) { - for (std::unique_ptr& b : d->m_DBufs) - b->update(m_completeBuf); - for (std::unique_ptr& t : d->m_DTexs) - t->update(m_completeBuf); + for (BaseGraphicsData& d : *gfxF->m_dataHead) + { + if (d.m_DBufs) + for (IGraphicsBufferD& b : *d.m_DBufs) + static_cast&>(b).update(m_completeBuf); + if (d.m_DTexs) + for (ITextureD& t : *d.m_DTexs) + static_cast(t).update(m_completeBuf); + } } - for (GLPool* p : gfxF->m_committedPools) + if (gfxF->m_poolHead) { - for (auto& b : p->m_items) - b->m_buf->update(m_completeBuf); + for (BaseGraphicsPool& p : *gfxF->m_poolHead) + { + if (p.m_DBufs) + for (IGraphicsBufferD& b : *p.m_DBufs) + static_cast&>(b).update(m_completeBuf); + } } datalk.unlock(); glFlush(); @@ -1628,7 +1432,8 @@ struct GLCommandQueue : IGraphicsCommandQueue } }; -void GLGraphicsBufferD::update(int b) +template +void GLGraphicsBufferD::update(int b) { int slot = 1 << b; if ((slot & m_validMask) == 0) @@ -1639,43 +1444,47 @@ void GLGraphicsBufferD::update(int b) } } -void GLGraphicsBufferD::load(const void* data, size_t sz) +template +void GLGraphicsBufferD::load(const void* data, size_t sz) { size_t bufSz = std::min(sz, m_cpuSz); memcpy(m_cpuBuf.get(), data, bufSz); m_validMask = 0; } -void* GLGraphicsBufferD::map(size_t sz) +template +void* GLGraphicsBufferD::map(size_t sz) { if (sz < m_cpuSz) return nullptr; return m_cpuBuf.get(); } -void GLGraphicsBufferD::unmap() +template +void GLGraphicsBufferD::unmap() { m_validMask = 0; } -void GLGraphicsBufferD::bindVertex(int b) +template +void GLGraphicsBufferD::bindVertex(int b) {glBindBuffer(GL_ARRAY_BUFFER, m_bufs[b]);} -void GLGraphicsBufferD::bindIndex(int b) +template +void GLGraphicsBufferD::bindIndex(int b) {glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[b]);} -void GLGraphicsBufferD::bindUniform(size_t idx, int b) +template +void GLGraphicsBufferD::bindUniform(size_t idx, int b) {glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[b]);} -void GLGraphicsBufferD::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b) +template +void GLGraphicsBufferD::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b) {glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_bufs[b], off, size);} -IGraphicsBufferD* +ObjToken GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); - GLGraphicsBufferD* retval = new GLGraphicsBufferD(d, use, stride * count); - d->m_DBufs.emplace_back(retval); - return retval; + return {new GLGraphicsBufferD(m_data, use, stride * count)}; } -GLTextureD::GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt, +GLTextureD::GLTextureD(const ObjToken& parent, size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode) -: boo::ITextureD(parent), m_width(width), m_height(height) +: GraphicsDataNode(parent), m_width(width), m_height(height) { int pxPitch = 4; switch (fmt) @@ -1706,7 +1515,7 @@ GLTextureD::GLTextureD(IGraphicsData* parent, size_t width, size_t height, Textu SetClampMode(GL_TEXTURE_2D, clampMode); } } -GLTextureD::~GLTextureD() {glDeleteTextures(3, m_texs);} +GLTextureD::~GLTextureD() { glDeleteTextures(3, m_texs); } void GLTextureD::update(int b) { @@ -1742,18 +1551,15 @@ void GLTextureD::bind(size_t idx, int b) glBindTexture(GL_TEXTURE_2D, m_texs[b]); } -ITextureD* +ObjToken GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode) { - GLData* d = GLDataFactoryImpl::m_deferredData.get(); - GLTextureD* retval = new GLTextureD(d, width, height, fmt, clampMode); - d->m_DTexs.emplace_back(retval); - return retval; + return {new GLTextureD(m_data, width, height, fmt, clampMode)}; } -GLTextureR::GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, - TextureClampMode clampMode, size_t colorBindingCount, size_t depthBindingCount) -: boo::ITextureR(parent), m_q(q), m_width(width), m_height(height), m_samples(samples) +GLTextureR::GLTextureR(const ObjToken& parent, GLCommandQueue* q, size_t width, size_t height, + size_t samples, TextureClampMode clampMode, size_t colorBindingCount, size_t depthBindingCount) +: GraphicsDataNode(parent), m_q(q), m_width(width), m_height(height), m_samples(samples) { glGenTextures(2, m_texs); if (colorBindingCount) @@ -1813,24 +1619,22 @@ GLTextureR::~GLTextureR() m_q->delFBO(this); } -ITextureR* +ObjToken GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, 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(d, q, width, height, factory.m_drawSamples, clampMode, - colorBindingCount, depthBindingCount); + ObjToken retval(new GLTextureR(m_data, q, width, height, factory.m_drawSamples, clampMode, + colorBindingCount, depthBindingCount)); q->resizeRenderTexture(retval, width, height); - GLDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval); return retval; } -GLVertexFormat::GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount, +GLVertexFormat::GLVertexFormat(const ObjToken& parent, GLCommandQueue* q, size_t elementCount, const VertexElementDescriptor* elements, size_t baseVert, size_t baseInst) -: boo::IVertexFormat(parent), +: GraphicsDataNode(parent), m_q(q), m_elementCount(elementCount), m_elements(new VertexElementDescriptor[elementCount]), @@ -1840,18 +1644,15 @@ GLVertexFormat::GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t m_elements[i] = elements[i]; m_q->addVertexFormat(this); } -GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);} +GLVertexFormat::~GLVertexFormat() { m_q->delVertexFormat(this); } -IVertexFormat* GLDataFactory::Context::newVertexFormat +ObjToken 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(d, q, elementCount, elements, baseVert, baseInst); - d->m_VFmts.emplace_back(retval); - return retval; + return {new GLVertexFormat(m_data, q, elementCount, elements, baseVert, baseInst)}; } IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent) diff --git a/lib/graphicsdev/Metal.mm b/lib/graphicsdev/Metal.mm index c361ecf..6e5e00e 100644 --- a/lib/graphicsdev/Metal.mm +++ b/lib/graphicsdev/Metal.mm @@ -29,77 +29,36 @@ struct MetalShareableShader : IShareableShader m_deferredData; - std::unordered_set m_committedData; - std::unordered_set m_committedPools; - std::mutex m_committedMutex; std::unordered_map> m_sharedShaders; struct MetalContext* m_ctx; uint32_t m_sampleCount; - void destroyData(IGraphicsData*); - void destroyAllData(); - void destroyPool(IGraphicsBufferPool*); - IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use, - size_t stride, size_t count); - void deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf); public: - MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount); + MetalDataFactoryImpl(const ObjToken& parent, MetalContext* ctx, uint32_t sampleCount); ~MetalDataFactoryImpl() = default; - Platform platform() const {return Platform::Metal;} - const char* platformName() const {return "Metal";} - - GraphicsDataToken commitTransaction(const std::function&); - GraphicsBufferPoolToken newBufferPool(); - + Platform platform() const { return Platform::Metal; } + const char* platformName() const { return "Metal"; } + void commitTransaction(const std::function&); + ObjToken newPoolBuffer(BufferUse use, size_t stride, size_t count); void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); } }; -ThreadLocalPtr MetalDataFactoryImpl::m_deferredData; -struct MetalData : IGraphicsDataPriv -{ - std::vector> m_SPs; - std::vector> m_SBinds; - std::vector> m_SBufs; - std::vector> m_DBufs; - std::vector> m_STexs; - std::vector> m_SATexs; - std::vector> m_DTexs; - std::vector> m_RTexs; - std::vector> m_VFmts; -}; - -struct MetalPoolItem : IGraphicsDataPriv -{ - std::unique_ptr m_buf; -}; - -struct MetalPool : IGraphicsBufferPool -{ - std::unordered_set m_items; - ~MetalPool() - { - for (auto& item : m_items) - item->decrement(); - } -}; - #define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared -class MetalGraphicsBufferS : public IGraphicsBufferS +class MetalGraphicsBufferS : public GraphicsDataNode { friend class MetalDataFactory; friend struct MetalCommandQueue; - MetalGraphicsBufferS(IGraphicsData* parent, BufferUse use, MetalContext* ctx, + MetalGraphicsBufferS(const ObjToken& 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) + : GraphicsDataNode(parent), m_stride(stride), m_count(count), m_sz(stride * count) { m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC]; } @@ -111,7 +70,8 @@ public: ~MetalGraphicsBufferS() = default; }; -class MetalGraphicsBufferD : public IGraphicsBufferD +template +class MetalGraphicsBufferD : public GraphicsDataNode { friend class MetalDataFactory; friend class MetalDataFactoryImpl; @@ -119,9 +79,10 @@ class MetalGraphicsBufferD : public IGraphicsBufferD MetalCommandQueue* m_q; std::unique_ptr m_cpuBuf; int m_validSlots = 0; - MetalGraphicsBufferD(IGraphicsData* parent, MetalCommandQueue* q, BufferUse use, + MetalGraphicsBufferD(const ObjToken& 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) + : GraphicsDataNode(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]; @@ -140,12 +101,12 @@ public: void unmap(); }; -class MetalTextureS : public ITextureS +class MetalTextureS : public GraphicsDataNode { friend class MetalDataFactory; - MetalTextureS(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t mips, + MetalTextureS(BaseGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t mips, TextureFormat fmt, const void* data, size_t sz) - : ITextureS(parent) + : GraphicsDataNode(parent) { MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; NSUInteger ppitchNum = 4; @@ -192,13 +153,13 @@ public: ~MetalTextureS() = default; }; -class MetalTextureSA : public ITextureSA +class MetalTextureSA : public GraphicsDataNode { friend class MetalDataFactory; - MetalTextureSA(IGraphicsData* parent, MetalContext* ctx, size_t width, + MetalTextureSA(BaseGraphicsData* 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) + : GraphicsDataNode(parent) { MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; NSUInteger ppitch = 4; @@ -247,7 +208,7 @@ public: ~MetalTextureSA() = default; }; -class MetalTextureD : public ITextureD +class MetalTextureD : public GraphicsDataNode { friend class MetalDataFactory; friend struct MetalCommandQueue; @@ -258,9 +219,9 @@ class MetalTextureD : public ITextureD size_t m_cpuSz; size_t m_pxPitch; int m_validSlots = 0; - MetalTextureD(IGraphicsData* parent, MetalCommandQueue* q, MetalContext* ctx, + MetalTextureD(BaseGraphicsData* 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) + : GraphicsDataNode(parent), m_q(q), m_width(width), m_height(height) { MTLPixelFormat format; switch (fmt) @@ -303,7 +264,7 @@ public: #define MAX_BIND_TEXS 4 -class MetalTextureR : public ITextureR +class MetalTextureR : public GraphicsDataNode { friend class MetalDataFactory; friend struct MetalCommandQueue; @@ -422,9 +383,9 @@ class MetalTextureR : public ITextureR } } - MetalTextureR(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t samples, + MetalTextureR(BaseGraphicsData* 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), + : GraphicsDataNode(parent), m_width(width), m_height(height), m_samples(samples), m_colorBindCount(colorBindCount), m_depthBindCount(depthBindCount) { @@ -485,14 +446,14 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] = MTLVertexFormatFloat4 }; -struct MetalVertexFormat : IVertexFormat +struct MetalVertexFormat : GraphicsDataNode { size_t m_elementCount; MTLVertexDescriptor* m_vdesc; size_t m_stride = 0; size_t m_instStride = 0; - MetalVertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements) - : boo::IVertexFormat(parent), m_elementCount(elementCount) + MetalVertexFormat(BaseGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements) + : GraphicsDataNode(parent), m_elementCount(elementCount) { for (size_t i=0 ; i { friend class MetalDataFactory; friend struct MetalCommandQueue; @@ -579,7 +540,7 @@ class MetalShaderPipeline : public IShaderPipeline MetalShareableShader::Token m_vert; MetalShareableShader::Token m_frag; - MetalShaderPipeline(IGraphicsData* parent, + MetalShaderPipeline(BaseGraphicsData* parent, MetalContext* ctx, MetalShareableShader::Token&& vert, MetalShareableShader::Token&& frag, @@ -587,7 +548,7 @@ class MetalShaderPipeline : public IShaderPipeline BlendFactor srcFac, BlendFactor dstFac, Primitive prim, ZTest depthTest, bool depthWrite, bool colorWrite, bool alphaWrite, CullMode culling) - : boo::IShaderPipeline(parent), + : GraphicsDataNode(parent), m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_frag(std::move(frag)) { @@ -734,7 +695,7 @@ static id GetTextureGPUResource(const ITexture* tex, int idx, int bi return nullptr; } -struct MetalShaderDataBinding : IShaderDataBindingPriv +struct MetalShaderDataBinding : GraphicsDataNode { MetalShaderPipeline* m_pipeline; IGraphicsBuffer* m_vbuf; @@ -764,7 +725,7 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv size_t texCount, ITexture** texs, const int* texBindIdxs, const bool* depthBind, size_t baseVert, size_t baseInst) - : IShaderDataBindingPriv(d), + : GraphicsDataNode(d), m_pipeline(static_cast(pipeline)), m_vbuf(vbuf), m_instVbo(instVbo), @@ -854,8 +815,8 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv struct MetalCommandQueue : IGraphicsCommandQueue { - Platform platform() const {return IGraphicsDataFactory::Platform::Metal;} - const char* platformName() const {return "Metal";} + Platform platform() const { return IGraphicsDataFactory::Platform::Metal; } + const char* platformName() const { return "Metal"; } MetalContext* m_ctx; IWindow* m_parentWindow; IGraphicsContext* m_parent; @@ -863,8 +824,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue id m_enc; bool m_running = true; - size_t m_fillBuf = 0; - size_t m_drawBuf = 0; + int m_fillBuf = 0; + int m_drawBuf = 0; MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent) : m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent) @@ -889,7 +850,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue MetalShaderDataBinding* m_boundData = nullptr; MTLPrimitiveType m_currentPrimitive = MTLPrimitiveTypeTriangle; - void setShaderDataBinding(IShaderDataBinding* binding) + void setShaderDataBinding(const ObjToken& binding) { @autoreleasepool { @@ -901,11 +862,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue } MetalTextureR* m_boundTarget = nullptr; - void _setRenderTarget(ITextureR* target, bool clearColor, bool clearDepth) + void _setRenderTarget(const ObjToken& target, bool clearColor, bool clearDepth) { - MetalTextureR* ctarget = static_cast(target); @autoreleasepool { + MetalTextureR* ctarget = target.cast(); [m_enc endEncoding]; if (clearColor && clearDepth) m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_clearBothPassDesc]; @@ -916,19 +877,19 @@ struct MetalCommandQueue : IGraphicsCommandQueue else m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc]; [m_enc setFrontFacingWinding:MTLWindingCounterClockwise]; + if (ctarget == m_boundTarget) + { + if (m_boundVp.width || m_boundVp.height) + [m_enc setViewport:m_boundVp]; + if (m_boundScissor.width || m_boundScissor.height) + [m_enc setScissorRect:m_boundScissor]; + } + else + m_boundTarget = ctarget; } - if (ctarget == m_boundTarget) - { - if (m_boundVp.width || m_boundVp.height) - [m_enc setViewport:m_boundVp]; - if (m_boundScissor.width || m_boundScissor.height) - [m_enc setScissorRect:m_boundScissor]; - } - else - m_boundTarget = ctarget; } - void setRenderTarget(ITextureR* target) + void setRenderTarget(const ObjToken& target) { _setRenderTarget(target, false, false); } @@ -955,9 +916,9 @@ struct MetalCommandQueue : IGraphicsCommandQueue } std::unordered_map> m_texResizes; - void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) + void resizeRenderTexture(const ObjToken& tex, size_t width, size_t height) { - MetalTextureR* ctex = static_cast(tex); + MetalTextureR* ctex = tex.cast(); m_texResizes[ctex] = std::make_pair(width, height); } @@ -968,7 +929,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue void flushBufferUpdates() {} - float m_clearColor[4] = {0.0,0.0,0.0,0.0}; + float m_clearColor[4] = {0.f,0.f,0.f,0.f}; void setClearColor(const float rgba[4]) { m_clearColor[0] = rgba[0]; @@ -1078,18 +1039,27 @@ struct MetalCommandQueue : IGraphicsCommandQueue /* Update dynamic data here */ MetalDataFactoryImpl* gfxF = static_cast(m_parent->getDataFactory()); - std::unique_lock datalk(gfxF->m_committedMutex); - for (MetalData* d : gfxF->m_committedData) + std::unique_lock datalk(gfxF->m_dataMutex); + if (gfxF->m_dataHead) { - for (std::unique_ptr& b : d->m_DBufs) - b->update(m_fillBuf); - for (std::unique_ptr& t : d->m_DTexs) - t->update(m_fillBuf); + for (BaseGraphicsData& d : *gfxF->m_dataHead) + { + if (d.m_DBufs) + for (IGraphicsBufferD& b : *d.m_DBufs) + static_cast&>(b).update(m_fillBuf); + if (d.m_DTexs) + for (ITextureD& t : *d.m_DTexs) + static_cast(t).update(m_fillBuf); + } } - for (MetalPool* p : gfxF->m_committedPools) + if (gfxF->m_poolHead) { - for (auto& b : p->m_items) - b->m_buf->update(m_fillBuf); + for (BaseGraphicsPool& p : *gfxF->m_poolHead) + { + if (p.m_DBufs) + for (IGraphicsBufferD& b : *p.m_DBufs) + static_cast&>(b).update(m_fillBuf); + } } datalk.unlock(); @@ -1389,13 +1359,15 @@ IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSo } } -IShaderDataBinding* -MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline, - IVertexFormat* vtxFormat, - IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf, - size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, +ObjToken +MetalDataFactory::Context::newShaderDataBinding(const ObjToken& pipeline, + const ObjToken& vtxFormat, + const ObjToken& vbo, + const ObjToken& instVbo, + const ObjToken& ibo, + size_t ubufCount, const ObjToken* ubufs, const PipelineStage* ubufStages, const size_t* ubufOffs, const size_t* ubufSizes, - size_t texCount, ITexture** texs, + size_t texCount, const ObjToken* texs, const int* texBindIdxs, const bool* depthBind, size_t baseVert, size_t baseInst) { @@ -1413,7 +1385,7 @@ MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline, } } -GraphicsDataToken MetalDataFactoryImpl::commitTransaction(const FactoryCommitFunc& trans) +void MetalDataFactoryImpl::commitTransaction(const FactoryCommitFunc& trans) { if (m_deferredData.get()) Log.report(logvisor::Fatal, "nested commitTransaction usage detected"); @@ -1434,62 +1406,11 @@ GraphicsDataToken MetalDataFactoryImpl::commitTransaction(const FactoryCommitFun return GraphicsDataToken(this, retval); } -GraphicsBufferPoolToken MetalDataFactoryImpl::newBufferPool() +ObjToken MetalDataFactoryImpl::newPoolBuffer(BufferUse use, size_t stride, size_t count) { - std::unique_lock lk(m_committedMutex); - MetalPool* retval = new MetalPool; - m_committedPools.insert(retval); - return GraphicsBufferPoolToken(this, retval); -} - -void MetalDataFactoryImpl::destroyData(IGraphicsData* d) -{ - std::unique_lock lk(m_committedMutex); - MetalData* data = static_cast(d); - m_committedData.erase(data); - data->decrement(); -} - -void MetalDataFactoryImpl::destroyAllData() -{ - std::unique_lock lk(m_committedMutex); - for (MetalData* data : m_committedData) - data->decrement(); - for (MetalPool* pool : m_committedPools) - delete pool; - m_committedData.clear(); - m_committedPools.clear(); -} - -void MetalDataFactoryImpl::destroyPool(IGraphicsBufferPool* p) -{ - std::unique_lock lk(m_committedMutex); - MetalPool* pool = static_cast(p); - m_committedPools.erase(pool); - delete pool; -} - -IGraphicsBufferD* MetalDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use, - size_t stride, size_t count) -{ - MetalPool* pool = static_cast(p); + ObjToken pool(new BaseGraphicsPool(*this)); MetalCommandQueue* q = static_cast(m_parent->getCommandQueue()); - 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); - auto search = pool->m_items.find(static_cast(buf->m_parentData)); - if (search != pool->m_items.end()) - { - (*search)->decrement(); - pool->m_items.erase(search); - } + return {MetalGraphicsBufferD(pool, q, use, m_ctx, stride, count)}; } IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, diff --git a/logvisor b/logvisor index bfe0c1c..f8ab0e0 160000 --- a/logvisor +++ b/logvisor @@ -1 +1 @@ -Subproject commit bfe0c1ccad9ee545a6ab9c0b295258c47b55da3c +Subproject commit f8ab0e03bae0cad2541f551350dcafb91477b007