mirror of https://github.com/AxioDL/boo.git
New object management architecture for OpenGL subsystem (more platforms to come)
This commit is contained in:
parent
90e2df40dd
commit
021143fd89
|
@ -285,6 +285,7 @@ add_library(boo
|
||||||
include/boo/ThreadLocalPtr.hpp
|
include/boo/ThreadLocalPtr.hpp
|
||||||
include/boo/DeferredWindowEvents.hpp
|
include/boo/DeferredWindowEvents.hpp
|
||||||
include/boo/System.hpp
|
include/boo/System.hpp
|
||||||
|
include/boo/BooObject.hpp
|
||||||
include/boo/boo.hpp
|
include/boo/boo.hpp
|
||||||
InputDeviceClasses.cpp
|
InputDeviceClasses.cpp
|
||||||
${PLAT_SRCS}
|
${PLAT_SRCS}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef BOOOBJECT_HPP
|
||||||
|
#define BOOOBJECT_HPP
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
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 SubCls>
|
||||||
|
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<class T> T* cast() const { return static_cast<T*>(m_obj); }
|
||||||
|
operator bool() const { return m_obj != nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BOOOBJECT_HPP
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
class BaseGraphicsData;
|
||||||
|
|
||||||
class GLDataFactory : public IGraphicsDataFactory
|
class GLDataFactory : public IGraphicsDataFactory
|
||||||
{
|
{
|
||||||
|
@ -16,40 +17,44 @@ public:
|
||||||
{
|
{
|
||||||
friend class GLDataFactoryImpl;
|
friend class GLDataFactoryImpl;
|
||||||
GLDataFactory& m_parent;
|
GLDataFactory& m_parent;
|
||||||
Context(GLDataFactory& parent) : m_parent(parent) {}
|
ObjToken<BaseGraphicsData> m_data;
|
||||||
|
Context(GLDataFactory& parent);
|
||||||
|
~Context();
|
||||||
public:
|
public:
|
||||||
Platform platform() const {return Platform::OpenGL;}
|
Platform platform() const { return Platform::OpenGL; }
|
||||||
const SystemChar* platformName() const {return _S("OpenGL");}
|
const SystemChar* platformName() const { return _S("OpenGL"); }
|
||||||
|
|
||||||
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
||||||
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
||||||
|
|
||||||
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
TextureClampMode clampMode, const void* data, size_t sz);
|
TextureClampMode clampMode, const void* data, size_t sz);
|
||||||
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
ObjToken<ITextureSA> 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);
|
||||||
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
|
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
|
||||||
ITextureR* newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
||||||
size_t colorBindingCount, size_t depthBindingCount);
|
size_t colorBindingCount, size_t depthBindingCount);
|
||||||
|
|
||||||
bool bindingNeedsVertexFormat() const {return true;}
|
bool bindingNeedsVertexFormat() const { return true; }
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
ObjToken<IVertexFormat> newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
size_t texCount, const char** texNames,
|
size_t texCount, const char** texNames,
|
||||||
size_t uniformBlockCount, const char** uniformBlockNames,
|
size_t uniformBlockCount, const char** uniformBlockNames,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||||
bool alphaWrite, CullMode culling);
|
bool alphaWrite, CullMode culling);
|
||||||
|
|
||||||
IShaderDataBinding*
|
ObjToken<IShaderDataBinding>
|
||||||
newShaderDataBinding(IShaderPipeline* pipeline,
|
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||||
IVertexFormat* vtxFormat,
|
const ObjToken<IVertexFormat>& vtxFormat,
|
||||||
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
const ObjToken<IGraphicsBuffer>& vbo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||||
|
const ObjToken<IGraphicsBuffer>& ibo,
|
||||||
|
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, const ObjToken<ITexture>* texs,
|
||||||
const int* texBindIdx, const bool* depthBind,
|
const int* texBindIdx, const bool* depthBind,
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,12 +16,12 @@ struct IGraphicsCommandQueue
|
||||||
virtual Platform platform() const=0;
|
virtual Platform platform() const=0;
|
||||||
virtual const SystemChar* platformName() const=0;
|
virtual const SystemChar* platformName() const=0;
|
||||||
|
|
||||||
virtual void setShaderDataBinding(IShaderDataBinding* binding)=0;
|
virtual void setShaderDataBinding(const ObjToken<IShaderDataBinding>& binding)=0;
|
||||||
virtual void setRenderTarget(ITextureR* target)=0;
|
virtual void setRenderTarget(const ObjToken<ITextureR>& target)=0;
|
||||||
virtual void setViewport(const SWindowRect& rect, float znear=0.f, float zfar=1.f)=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 setScissor(const SWindowRect& rect)=0;
|
||||||
|
|
||||||
virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0;
|
virtual void resizeRenderTexture(const ObjToken<ITextureR>& tex, size_t width, size_t height)=0;
|
||||||
virtual void schedulePostFrameHandler(std::function<void(void)>&& func)=0;
|
virtual void schedulePostFrameHandler(std::function<void(void)>&& func)=0;
|
||||||
|
|
||||||
virtual void setClearColor(const float rgba[4])=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 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 drawInstancesIndexed(size_t start, size_t count, size_t instCount)=0;
|
||||||
|
|
||||||
virtual void resolveBindTexture(ITextureR* texture, const SWindowRect& rect,
|
virtual void resolveBindTexture(const ObjToken<ITextureR>& texture, const SWindowRect& rect,
|
||||||
bool tlOrigin, int bindIdx, bool color, bool depth)=0;
|
bool tlOrigin, int bindIdx, bool color, bool depth)=0;
|
||||||
virtual void resolveDisplay(ITextureR* source)=0;
|
virtual void resolveDisplay(const ObjToken<ITextureR>& source)=0;
|
||||||
virtual void execute()=0;
|
virtual void execute()=0;
|
||||||
|
|
||||||
virtual void stopRenderer()=0;
|
virtual void stopRenderer()=0;
|
||||||
|
|
|
@ -6,47 +6,12 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "boo/System.hpp"
|
#include "boo/System.hpp"
|
||||||
#include "boo/ThreadLocalPtr.hpp"
|
#include "boo/ThreadLocalPtr.hpp"
|
||||||
|
#include "boo/BooObject.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
struct IGraphicsCommandQueue;
|
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 */
|
/** Supported buffer uses */
|
||||||
enum class BufferUse
|
enum class BufferUse
|
||||||
{
|
{
|
||||||
|
@ -56,6 +21,33 @@ enum class BufferUse
|
||||||
Uniform
|
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
|
enum class TextureType
|
||||||
{
|
{
|
||||||
Static,
|
Static,
|
||||||
|
@ -64,48 +56,6 @@ enum class TextureType
|
||||||
Render
|
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 */
|
/** Supported texture formats */
|
||||||
enum class TextureFormat
|
enum class TextureFormat
|
||||||
{
|
{
|
||||||
|
@ -115,21 +65,57 @@ enum class TextureFormat
|
||||||
PVRTC4
|
PVRTC4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Supported texture clamp modes */
|
||||||
enum class TextureClampMode
|
enum class TextureClampMode
|
||||||
{
|
{
|
||||||
Repeat,
|
Repeat,
|
||||||
ClampToWhite
|
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
|
/** Opaque token for representing the data layout of a vertex
|
||||||
* in a VBO. Also able to reference buffers for platforms like
|
* in a VBO. Also able to reference buffers for platforms like
|
||||||
* OpenGL that cache object refs */
|
* OpenGL that cache object refs */
|
||||||
struct IVertexFormat
|
struct IVertexFormat : IObj {};
|
||||||
{
|
|
||||||
IGraphicsData* m_parentData;
|
|
||||||
protected:
|
|
||||||
IVertexFormat(IGraphicsData* parent) : m_parentData(parent) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Types of vertex attributes */
|
/** Types of vertex attributes */
|
||||||
enum class VertexSemantic
|
enum class VertexSemantic
|
||||||
|
@ -164,17 +150,12 @@ struct VertexElementDescriptor
|
||||||
|
|
||||||
/** Opaque token for referencing a complete graphics pipeline state necessary
|
/** Opaque token for referencing a complete graphics pipeline state necessary
|
||||||
* to rasterize geometry (shaders and blending modes mainly) */
|
* to rasterize geometry (shaders and blending modes mainly) */
|
||||||
struct IShaderPipeline
|
struct IShaderPipeline : IObj {};
|
||||||
{
|
|
||||||
IGraphicsData* m_parentData;
|
|
||||||
protected:
|
|
||||||
IShaderPipeline(IGraphicsData* parent) : m_parentData(parent) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Opaque token serving as indirection table for shader resources
|
/** Opaque token serving as indirection table for shader resources
|
||||||
* and IShaderPipeline reference. Each renderable surface-material holds one
|
* and IShaderPipeline reference. Each renderable surface-material holds one
|
||||||
* as a reference */
|
* as a reference */
|
||||||
struct IShaderDataBinding {};
|
struct IShaderDataBinding : IObj {};
|
||||||
|
|
||||||
/** Used wherever distinction of pipeline stages is needed */
|
/** Used wherever distinction of pipeline stages is needed */
|
||||||
enum class PipelineStage
|
enum class PipelineStage
|
||||||
|
@ -252,44 +233,48 @@ struct IGraphicsDataFactory
|
||||||
virtual Platform platform() const=0;
|
virtual Platform platform() const=0;
|
||||||
virtual const SystemChar* platformName() const=0;
|
virtual const SystemChar* platformName() const=0;
|
||||||
|
|
||||||
virtual IGraphicsBufferS*
|
virtual ObjToken<IGraphicsBufferS>
|
||||||
newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0;
|
newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0;
|
||||||
virtual IGraphicsBufferD*
|
virtual ObjToken<IGraphicsBufferD>
|
||||||
newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0;
|
newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0;
|
||||||
|
|
||||||
virtual ITextureS*
|
virtual ObjToken<ITextureS>
|
||||||
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
TextureClampMode clampMode, const void* data, size_t sz)=0;
|
TextureClampMode clampMode, const void* data, size_t sz)=0;
|
||||||
virtual ITextureSA*
|
virtual ObjToken<ITextureSA>
|
||||||
newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
||||||
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz)=0;
|
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz)=0;
|
||||||
virtual ITextureD*
|
virtual ObjToken<ITextureD>
|
||||||
newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode)=0;
|
newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode)=0;
|
||||||
virtual ITextureR*
|
virtual ObjToken<ITextureR>
|
||||||
newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
||||||
size_t colorBindingCount, size_t depthBindingCount)=0;
|
size_t colorBindingCount, size_t depthBindingCount)=0;
|
||||||
|
|
||||||
virtual bool bindingNeedsVertexFormat() const=0;
|
virtual bool bindingNeedsVertexFormat() const=0;
|
||||||
virtual IVertexFormat*
|
virtual ObjToken<IVertexFormat>
|
||||||
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
size_t baseVert = 0, size_t baseInst = 0)=0;
|
size_t baseVert = 0, size_t baseInst = 0)=0;
|
||||||
|
|
||||||
virtual IShaderDataBinding*
|
virtual ObjToken<IShaderDataBinding>
|
||||||
newShaderDataBinding(IShaderPipeline* pipeline,
|
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||||
IVertexFormat* vtxFormat,
|
const ObjToken<IVertexFormat>& vtxFormat,
|
||||||
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
const ObjToken<IGraphicsBuffer>& vbo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||||
|
const ObjToken<IGraphicsBuffer>& ibo,
|
||||||
|
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, const ObjToken<ITexture>* texs,
|
||||||
const int* texBindIdx, const bool* depthBind,
|
const int* texBindIdx, const bool* depthBind,
|
||||||
size_t baseVert = 0, size_t baseInst = 0)=0;
|
size_t baseVert = 0, size_t baseInst = 0)=0;
|
||||||
|
|
||||||
IShaderDataBinding*
|
ObjToken<IShaderDataBinding>
|
||||||
newShaderDataBinding(IShaderPipeline* pipeline,
|
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||||
IVertexFormat* vtxFormat,
|
const ObjToken<IVertexFormat>& vtxFormat,
|
||||||
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
const ObjToken<IGraphicsBuffer>& vbo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||||
size_t texCount, ITexture** texs,
|
const ObjToken<IGraphicsBuffer>& ibo,
|
||||||
|
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
|
||||||
|
size_t texCount, const ObjToken<ITexture>* texs,
|
||||||
const int* texBindIdx, const bool* depthBind,
|
const int* texBindIdx, const bool* depthBind,
|
||||||
size_t baseVert = 0, size_t baseInst = 0)
|
size_t baseVert = 0, size_t baseInst = 0)
|
||||||
{
|
{
|
||||||
|
@ -300,130 +285,13 @@ struct IGraphicsDataFactory
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual GraphicsDataToken commitTransaction(const std::function<bool(Context& ctx)>&)=0;
|
virtual void commitTransaction(const std::function<bool(Context& ctx)>&)=0;
|
||||||
virtual GraphicsBufferPoolToken newBufferPool()=0;
|
|
||||||
|
|
||||||
virtual void destroyAllData()=0;
|
virtual ObjToken<IGraphicsBufferD> newPoolBuffer(BufferUse use, size_t stride, size_t count)=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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using FactoryCommitFunc = std::function<bool(IGraphicsDataFactory::Context& ctx)>;
|
using GraphicsDataFactoryContext = IGraphicsDataFactory::Context;
|
||||||
|
using FactoryCommitFunc = std::function<bool(GraphicsDataFactoryContext& ctx)>;
|
||||||
/** 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,37 +19,41 @@ public:
|
||||||
MetalDataFactory& m_parent;
|
MetalDataFactory& m_parent;
|
||||||
Context(MetalDataFactory& parent) : m_parent(parent) {}
|
Context(MetalDataFactory& parent) : m_parent(parent) {}
|
||||||
public:
|
public:
|
||||||
Platform platform() const {return Platform::Metal;}
|
Platform platform() const { return Platform::Metal; }
|
||||||
const char* platformName() const {return "Metal";}
|
const SystemChar* platformName() const { return _S("Metal"); }
|
||||||
|
|
||||||
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
ObjToken<IGraphicsBufferS> newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
||||||
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
ObjToken<IGraphicsBufferD> newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
||||||
|
|
||||||
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
ObjToken<ITextureS> newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
TextureClampMode clampMode, const void* data, size_t sz);
|
TextureClampMode clampMode, const void* data, size_t sz);
|
||||||
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips,
|
ObjToken<ITextureSA> 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,
|
||||||
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
|
size_t sz);
|
||||||
ITextureR* newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
ObjToken<ITextureD> newDynamicTexture(size_t width, size_t height, TextureFormat fmt,
|
||||||
size_t colorBindCount, size_t depthBindCount);
|
TextureClampMode clampMode);
|
||||||
|
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
||||||
|
size_t colorBindCount, size_t depthBindCount);
|
||||||
|
|
||||||
bool bindingNeedsVertexFormat() const {return false;}
|
bool bindingNeedsVertexFormat() const { return false; }
|
||||||
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
ObjToken<IVertexFormat> newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
IVertexFormat* vtxFmt, unsigned targetSamples,
|
IVertexFormat* vtxFmt, unsigned targetSamples,
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||||
bool alphaWrite, CullMode culling);
|
bool alphaWrite, CullMode culling);
|
||||||
|
|
||||||
IShaderDataBinding*
|
ObjToken<IShaderDataBinding>
|
||||||
newShaderDataBinding(IShaderPipeline* pipeline,
|
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||||
IVertexFormat* vtxFormat,
|
const ObjToken<IVertexFormat>& vtxFormat,
|
||||||
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
|
const ObjToken<IGraphicsBuffer>& vbo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||||
|
const ObjToken<IGraphicsBuffer>& ibo,
|
||||||
|
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, const ObjToken<ITexture>* texs,
|
||||||
const int* texBindIdxs, const bool* depthBind,
|
const int* texBindIdxs, const bool* depthBind,
|
||||||
size_t baseVert = 0, size_t baseInst = 0);
|
size_t baseVert = 0, size_t baseInst = 0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,63 +6,219 @@
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
|
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
|
||||||
class IGraphicsDataPriv : public IGraphicsData
|
struct BaseGraphicsData;
|
||||||
|
struct BaseGraphicsPool;
|
||||||
|
|
||||||
|
template<class NodeCls, class DataCls = BaseGraphicsData>
|
||||||
|
struct GraphicsDataNode;
|
||||||
|
|
||||||
|
/** Inherited by data factory implementations to track the head data and pool nodes */
|
||||||
|
struct GraphicsDataFactoryHead
|
||||||
{
|
{
|
||||||
std::atomic_int m_refCount = {1};
|
std::mutex m_dataMutex;
|
||||||
public:
|
BaseGraphicsData* m_dataHead = nullptr;
|
||||||
void increment() { m_refCount++; }
|
BaseGraphicsPool* m_poolHead = nullptr;
|
||||||
void decrement()
|
|
||||||
{
|
|
||||||
if (m_refCount.fetch_sub(1) == 1)
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IShaderDataBindingPriv : public IShaderDataBinding
|
/** Private generalized data container class.
|
||||||
|
* Keeps head pointers to all graphics objects by type
|
||||||
|
*/
|
||||||
|
struct BaseGraphicsData : IObj
|
||||||
{
|
{
|
||||||
IGraphicsDataPriv* m_parent;
|
GraphicsDataFactoryHead& m_head;
|
||||||
std::vector<IGraphicsDataPriv*> m_depDatas;
|
BaseGraphicsData* m_next;
|
||||||
|
BaseGraphicsData* m_prev = nullptr;
|
||||||
|
GraphicsDataNode<IShaderPipeline, BaseGraphicsData>* m_SPs = nullptr;
|
||||||
|
GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>* m_SBinds = nullptr;
|
||||||
|
GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>* m_SBufs = nullptr;
|
||||||
|
GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>* m_DBufs = nullptr;
|
||||||
|
GraphicsDataNode<ITextureS, BaseGraphicsData>* m_STexs = nullptr;
|
||||||
|
GraphicsDataNode<ITextureSA, BaseGraphicsData>* m_SATexs = nullptr;
|
||||||
|
GraphicsDataNode<ITextureD, BaseGraphicsData>* m_DTexs = nullptr;
|
||||||
|
GraphicsDataNode<ITextureR, BaseGraphicsData>* m_RTexs = nullptr;
|
||||||
|
GraphicsDataNode<IVertexFormat, BaseGraphicsData>* m_VFmts = nullptr;
|
||||||
|
template<class T> GraphicsDataNode<T, BaseGraphicsData>*& getHead();
|
||||||
|
|
||||||
public:
|
explicit BaseGraphicsData(GraphicsDataFactoryHead& head)
|
||||||
IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {}
|
: m_head(head)
|
||||||
class Token
|
|
||||||
{
|
{
|
||||||
IGraphicsDataPriv* m_data = nullptr;
|
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
|
||||||
public:
|
m_next = head.m_dataHead;
|
||||||
Token() = default;
|
head.m_dataHead = this;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
~BaseGraphicsData()
|
||||||
protected:
|
|
||||||
void addDepData(IGraphicsData* data)
|
|
||||||
{
|
{
|
||||||
IGraphicsDataPriv* d = static_cast<IGraphicsDataPriv*>(data);
|
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
|
||||||
if (d != m_parent)
|
if (m_prev)
|
||||||
{
|
{
|
||||||
m_depDatas.push_back(d);
|
if (m_next)
|
||||||
d->increment();
|
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<IShaderPipeline, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<IShaderPipeline>() { return m_SPs; }
|
||||||
|
template <> GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<IShaderDataBinding>() { return m_SBinds; }
|
||||||
|
template <> GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<IGraphicsBufferS>() { return m_SBufs; }
|
||||||
|
template <> GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<IGraphicsBufferD>() { return m_DBufs; }
|
||||||
|
template <> GraphicsDataNode<ITextureS, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<ITextureS>() { return m_STexs; }
|
||||||
|
template <> GraphicsDataNode<ITextureSA, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<ITextureSA>() { return m_SATexs; }
|
||||||
|
template <> GraphicsDataNode<ITextureD, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<ITextureD>() { return m_DTexs; }
|
||||||
|
template <> GraphicsDataNode<ITextureR, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<ITextureR>() { return m_RTexs; }
|
||||||
|
template <> GraphicsDataNode<IVertexFormat, BaseGraphicsData>*&
|
||||||
|
BaseGraphicsData::getHead<IVertexFormat>() { 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<IGraphicsBufferD, BaseGraphicsPool>* m_DBufs = nullptr;
|
||||||
|
template<class T> GraphicsDataNode<T, BaseGraphicsPool>*& getHead();
|
||||||
|
|
||||||
|
explicit BaseGraphicsPool(GraphicsDataFactoryHead& head)
|
||||||
|
: m_head(head)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
|
||||||
|
m_next = head.m_poolHead;
|
||||||
|
head.m_poolHead = this;
|
||||||
|
}
|
||||||
|
~BaseGraphicsPool()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> 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<IGraphicsBufferD, BaseGraphicsPool>*&
|
||||||
|
BaseGraphicsPool::getHead<IGraphicsBufferD>() { 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<class NodeCls, class DataCls>
|
||||||
|
struct GraphicsDataNode : NodeCls
|
||||||
|
{
|
||||||
|
ObjToken<DataCls> m_data;
|
||||||
|
GraphicsDataNode<NodeCls, DataCls>* m_next;
|
||||||
|
GraphicsDataNode<NodeCls, DataCls>* m_prev = nullptr;
|
||||||
|
|
||||||
|
explicit GraphicsDataNode(const ObjToken<DataCls>& data)
|
||||||
|
: m_data(data)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(m_data->m_head.m_dataMutex);
|
||||||
|
m_next = data->template getHead<NodeCls>();
|
||||||
|
data->template getHead<NodeCls>() = this;
|
||||||
|
}
|
||||||
|
~GraphicsDataNode()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> 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<NodeCls>();
|
||||||
|
m_data->template getHead<NodeCls>() = m_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator
|
||||||
|
{
|
||||||
|
GraphicsDataNode<NodeCls, DataCls>* m_node;
|
||||||
|
public:
|
||||||
|
using value_type = NodeCls;
|
||||||
|
using pointer = NodeCls*;
|
||||||
|
using reference = NodeCls&;
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
|
||||||
|
explicit iterator(GraphicsDataNode<NodeCls, DataCls>* 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 <class FactoryImpl, class ShaderImpl>
|
template <class FactoryImpl, class ShaderImpl>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,77 +29,36 @@ struct MetalShareableShader : IShareableShader<MetalDataFactoryImpl, MetalSharea
|
||||||
: IShareableShader(fac, srcKey, 0), m_shader(s) {}
|
: IShareableShader(fac, srcKey, 0), m_shader(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalDataFactoryImpl : public MetalDataFactory
|
class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactoryHead
|
||||||
{
|
{
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
friend class MetalDataFactory::Context;
|
friend class MetalDataFactory::Context;
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
static ThreadLocalPtr<struct MetalData> m_deferredData;
|
|
||||||
std::unordered_set<struct MetalData*> m_committedData;
|
|
||||||
std::unordered_set<struct MetalPool*> m_committedPools;
|
|
||||||
std::mutex m_committedMutex;
|
|
||||||
std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders;
|
std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders;
|
||||||
struct MetalContext* m_ctx;
|
struct MetalContext* m_ctx;
|
||||||
uint32_t m_sampleCount;
|
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:
|
public:
|
||||||
MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount);
|
MetalDataFactoryImpl(const ObjToken<BaseGraphicsData>& parent, MetalContext* ctx, uint32_t sampleCount);
|
||||||
~MetalDataFactoryImpl() = default;
|
~MetalDataFactoryImpl() = default;
|
||||||
|
|
||||||
Platform platform() const {return Platform::Metal;}
|
Platform platform() const { return Platform::Metal; }
|
||||||
const char* platformName() const {return "Metal";}
|
const char* platformName() const { return "Metal"; }
|
||||||
|
void commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&);
|
||||||
GraphicsDataToken commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&);
|
ObjToken<IGraphicsBufferD> newPoolBuffer(BufferUse use, size_t stride, size_t count);
|
||||||
GraphicsBufferPoolToken newBufferPool();
|
|
||||||
|
|
||||||
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); }
|
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); }
|
||||||
};
|
};
|
||||||
|
|
||||||
ThreadLocalPtr<struct MetalData> MetalDataFactoryImpl::m_deferredData;
|
|
||||||
struct MetalData : IGraphicsDataPriv
|
|
||||||
{
|
|
||||||
std::vector<std::unique_ptr<class MetalShaderPipeline>> m_SPs;
|
|
||||||
std::vector<std::unique_ptr<struct MetalShaderDataBinding>> m_SBinds;
|
|
||||||
std::vector<std::unique_ptr<class MetalGraphicsBufferS>> m_SBufs;
|
|
||||||
std::vector<std::unique_ptr<class MetalGraphicsBufferD>> m_DBufs;
|
|
||||||
std::vector<std::unique_ptr<class MetalTextureS>> m_STexs;
|
|
||||||
std::vector<std::unique_ptr<class MetalTextureSA>> m_SATexs;
|
|
||||||
std::vector<std::unique_ptr<class MetalTextureD>> m_DTexs;
|
|
||||||
std::vector<std::unique_ptr<class MetalTextureR>> m_RTexs;
|
|
||||||
std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MetalPoolItem : IGraphicsDataPriv
|
|
||||||
{
|
|
||||||
std::unique_ptr<class MetalGraphicsBufferD> m_buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MetalPool : IGraphicsBufferPool
|
|
||||||
{
|
|
||||||
std::unordered_set<MetalPoolItem*> m_items;
|
|
||||||
~MetalPool()
|
|
||||||
{
|
|
||||||
for (auto& item : m_items)
|
|
||||||
item->decrement();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
|
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
|
||||||
#define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
|
#define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
|
||||||
|
|
||||||
class MetalGraphicsBufferS : public IGraphicsBufferS
|
class MetalGraphicsBufferS : public GraphicsDataNode<IGraphicsBufferS>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
MetalGraphicsBufferS(IGraphicsData* parent, BufferUse use, MetalContext* ctx,
|
MetalGraphicsBufferS(const ObjToken<BaseGraphicsData>& parent, BufferUse use, MetalContext* ctx,
|
||||||
const void* data, size_t stride, size_t count)
|
const void* data, size_t stride, size_t count)
|
||||||
: boo::IGraphicsBufferS(parent), m_stride(stride), m_count(count), m_sz(stride * count)
|
: GraphicsDataNode<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];
|
m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC];
|
||||||
}
|
}
|
||||||
|
@ -111,7 +70,8 @@ public:
|
||||||
~MetalGraphicsBufferS() = default;
|
~MetalGraphicsBufferS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalGraphicsBufferD : public IGraphicsBufferD
|
template<class DataCls>
|
||||||
|
class MetalGraphicsBufferD : public GraphicsDataNode<IGraphicsBufferD, DataCls>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend class MetalDataFactoryImpl;
|
friend class MetalDataFactoryImpl;
|
||||||
|
@ -119,9 +79,10 @@ class MetalGraphicsBufferD : public IGraphicsBufferD
|
||||||
MetalCommandQueue* m_q;
|
MetalCommandQueue* m_q;
|
||||||
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
||||||
int m_validSlots = 0;
|
int m_validSlots = 0;
|
||||||
MetalGraphicsBufferD(IGraphicsData* parent, MetalCommandQueue* q, BufferUse use,
|
MetalGraphicsBufferD(const ObjToken<BaseGraphicsData>& parent, MetalCommandQueue* q, BufferUse use,
|
||||||
MetalContext* ctx, size_t stride, size_t count)
|
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<IGraphicsBufferD, DataCls>(parent), m_q(q), m_stride(stride),
|
||||||
|
m_count(count), m_sz(stride * count)
|
||||||
{
|
{
|
||||||
m_cpuBuf.reset(new uint8_t[m_sz]);
|
m_cpuBuf.reset(new uint8_t[m_sz]);
|
||||||
m_bufs[0] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
m_bufs[0] = [ctx->m_dev newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
||||||
|
@ -140,12 +101,12 @@ public:
|
||||||
void unmap();
|
void unmap();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureS : public ITextureS
|
class MetalTextureS : public GraphicsDataNode<ITextureS>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
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)
|
TextureFormat fmt, const void* data, size_t sz)
|
||||||
: ITextureS(parent)
|
: GraphicsDataNode<ITextureS>(parent)
|
||||||
{
|
{
|
||||||
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
||||||
NSUInteger ppitchNum = 4;
|
NSUInteger ppitchNum = 4;
|
||||||
|
@ -192,13 +153,13 @@ public:
|
||||||
~MetalTextureS() = default;
|
~MetalTextureS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureSA : public ITextureSA
|
class MetalTextureSA : public GraphicsDataNode<ITextureSA>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
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,
|
size_t height, size_t layers, size_t mips,
|
||||||
TextureFormat fmt, const void* data, size_t sz)
|
TextureFormat fmt, const void* data, size_t sz)
|
||||||
: ITextureSA(parent)
|
: GraphicsDataNode<ITextureSA>(parent)
|
||||||
{
|
{
|
||||||
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
||||||
NSUInteger ppitch = 4;
|
NSUInteger ppitch = 4;
|
||||||
|
@ -247,7 +208,7 @@ public:
|
||||||
~MetalTextureSA() = default;
|
~MetalTextureSA() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureD : public ITextureD
|
class MetalTextureD : public GraphicsDataNode<ITextureD>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
|
@ -258,9 +219,9 @@ class MetalTextureD : public ITextureD
|
||||||
size_t m_cpuSz;
|
size_t m_cpuSz;
|
||||||
size_t m_pxPitch;
|
size_t m_pxPitch;
|
||||||
int m_validSlots = 0;
|
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)
|
size_t width, size_t height, TextureFormat fmt)
|
||||||
: boo::ITextureD(parent), m_q(q), m_width(width), m_height(height)
|
: GraphicsDataNode<ITextureD>(parent), m_q(q), m_width(width), m_height(height)
|
||||||
{
|
{
|
||||||
MTLPixelFormat format;
|
MTLPixelFormat format;
|
||||||
switch (fmt)
|
switch (fmt)
|
||||||
|
@ -303,7 +264,7 @@ public:
|
||||||
|
|
||||||
#define MAX_BIND_TEXS 4
|
#define MAX_BIND_TEXS 4
|
||||||
|
|
||||||
class MetalTextureR : public ITextureR
|
class MetalTextureR : public GraphicsDataNode<ITextureR>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend struct MetalCommandQueue;
|
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)
|
size_t colorBindCount, size_t depthBindCount)
|
||||||
: boo::ITextureR(parent), m_width(width), m_height(height), m_samples(samples),
|
: GraphicsDataNode<ITextureR>(parent), m_width(width), m_height(height), m_samples(samples),
|
||||||
m_colorBindCount(colorBindCount),
|
m_colorBindCount(colorBindCount),
|
||||||
m_depthBindCount(depthBindCount)
|
m_depthBindCount(depthBindCount)
|
||||||
{
|
{
|
||||||
|
@ -485,14 +446,14 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] =
|
||||||
MTLVertexFormatFloat4
|
MTLVertexFormatFloat4
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MetalVertexFormat : IVertexFormat
|
struct MetalVertexFormat : GraphicsDataNode<IVertexFormat>
|
||||||
{
|
{
|
||||||
size_t m_elementCount;
|
size_t m_elementCount;
|
||||||
MTLVertexDescriptor* m_vdesc;
|
MTLVertexDescriptor* m_vdesc;
|
||||||
size_t m_stride = 0;
|
size_t m_stride = 0;
|
||||||
size_t m_instStride = 0;
|
size_t m_instStride = 0;
|
||||||
MetalVertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements)
|
MetalVertexFormat(BaseGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: boo::IVertexFormat(parent), m_elementCount(elementCount)
|
: GraphicsDataNode<ITextureFormat>(parent), m_elementCount(elementCount)
|
||||||
{
|
{
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
{
|
{
|
||||||
|
@ -568,7 +529,7 @@ static const MTLPrimitiveType PRIMITIVE_TABLE[] =
|
||||||
|
|
||||||
#define COLOR_WRITE_MASK (MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue)
|
#define COLOR_WRITE_MASK (MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue)
|
||||||
|
|
||||||
class MetalShaderPipeline : public IShaderPipeline
|
class MetalShaderPipeline : public GraphicsDataNode<IShaderPipeline>
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
|
@ -579,7 +540,7 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
MetalShareableShader::Token m_vert;
|
MetalShareableShader::Token m_vert;
|
||||||
MetalShareableShader::Token m_frag;
|
MetalShareableShader::Token m_frag;
|
||||||
|
|
||||||
MetalShaderPipeline(IGraphicsData* parent,
|
MetalShaderPipeline(BaseGraphicsData* parent,
|
||||||
MetalContext* ctx,
|
MetalContext* ctx,
|
||||||
MetalShareableShader::Token&& vert,
|
MetalShareableShader::Token&& vert,
|
||||||
MetalShareableShader::Token&& frag,
|
MetalShareableShader::Token&& frag,
|
||||||
|
@ -587,7 +548,7 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||||
bool alphaWrite, CullMode culling)
|
bool alphaWrite, CullMode culling)
|
||||||
: boo::IShaderPipeline(parent),
|
: GraphicsDataNode<IShaderPipeline>(parent),
|
||||||
m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt),
|
m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt),
|
||||||
m_vert(std::move(vert)), m_frag(std::move(frag))
|
m_vert(std::move(vert)), m_frag(std::move(frag))
|
||||||
{
|
{
|
||||||
|
@ -734,7 +695,7 @@ static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx, int bi
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MetalShaderDataBinding : IShaderDataBindingPriv
|
struct MetalShaderDataBinding : GraphicsDataNode<IShaderDataBinding>
|
||||||
{
|
{
|
||||||
MetalShaderPipeline* m_pipeline;
|
MetalShaderPipeline* m_pipeline;
|
||||||
IGraphicsBuffer* m_vbuf;
|
IGraphicsBuffer* m_vbuf;
|
||||||
|
@ -764,7 +725,7 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, ITexture** texs,
|
||||||
const int* texBindIdxs, const bool* depthBind,
|
const int* texBindIdxs, const bool* depthBind,
|
||||||
size_t baseVert, size_t baseInst)
|
size_t baseVert, size_t baseInst)
|
||||||
: IShaderDataBindingPriv(d),
|
: GraphicsDataNode<IShaderDataBinding>(d),
|
||||||
m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)),
|
m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)),
|
||||||
m_vbuf(vbuf),
|
m_vbuf(vbuf),
|
||||||
m_instVbo(instVbo),
|
m_instVbo(instVbo),
|
||||||
|
@ -854,8 +815,8 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv
|
||||||
|
|
||||||
struct MetalCommandQueue : IGraphicsCommandQueue
|
struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
Platform platform() const {return IGraphicsDataFactory::Platform::Metal;}
|
Platform platform() const { return IGraphicsDataFactory::Platform::Metal; }
|
||||||
const char* platformName() const {return "Metal";}
|
const char* platformName() const { return "Metal"; }
|
||||||
MetalContext* m_ctx;
|
MetalContext* m_ctx;
|
||||||
IWindow* m_parentWindow;
|
IWindow* m_parentWindow;
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
|
@ -863,8 +824,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
id<MTLRenderCommandEncoder> m_enc;
|
id<MTLRenderCommandEncoder> m_enc;
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
|
|
||||||
size_t m_fillBuf = 0;
|
int m_fillBuf = 0;
|
||||||
size_t m_drawBuf = 0;
|
int m_drawBuf = 0;
|
||||||
|
|
||||||
MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent)
|
MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent)
|
||||||
: m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent)
|
: m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent)
|
||||||
|
@ -889,7 +850,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
MetalShaderDataBinding* m_boundData = nullptr;
|
MetalShaderDataBinding* m_boundData = nullptr;
|
||||||
MTLPrimitiveType m_currentPrimitive = MTLPrimitiveTypeTriangle;
|
MTLPrimitiveType m_currentPrimitive = MTLPrimitiveTypeTriangle;
|
||||||
void setShaderDataBinding(IShaderDataBinding* binding)
|
void setShaderDataBinding(const ObjToken<IShaderDataBinding>& binding)
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
@ -901,11 +862,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalTextureR* m_boundTarget = nullptr;
|
MetalTextureR* m_boundTarget = nullptr;
|
||||||
void _setRenderTarget(ITextureR* target, bool clearColor, bool clearDepth)
|
void _setRenderTarget(const ObjToken<ITextureR>& target, bool clearColor, bool clearDepth)
|
||||||
{
|
{
|
||||||
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
|
MetalTextureR* ctarget = target.cast<MetalTextureR>();
|
||||||
[m_enc endEncoding];
|
[m_enc endEncoding];
|
||||||
if (clearColor && clearDepth)
|
if (clearColor && clearDepth)
|
||||||
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_clearBothPassDesc];
|
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_clearBothPassDesc];
|
||||||
|
@ -916,19 +877,19 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
else
|
else
|
||||||
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc];
|
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc];
|
||||||
[m_enc setFrontFacingWinding:MTLWindingCounterClockwise];
|
[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<ITextureR>& target)
|
||||||
{
|
{
|
||||||
_setRenderTarget(target, false, false);
|
_setRenderTarget(target, false, false);
|
||||||
}
|
}
|
||||||
|
@ -955,9 +916,9 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<MetalTextureR*, std::pair<size_t, size_t>> m_texResizes;
|
std::unordered_map<MetalTextureR*, std::pair<size_t, size_t>> m_texResizes;
|
||||||
void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)
|
void resizeRenderTexture(const ObjToken<ITextureR>& tex, size_t width, size_t height)
|
||||||
{
|
{
|
||||||
MetalTextureR* ctex = static_cast<MetalTextureR*>(tex);
|
MetalTextureR* ctex = tex.cast<MetalTextureR>();
|
||||||
m_texResizes[ctex] = std::make_pair(width, height);
|
m_texResizes[ctex] = std::make_pair(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,7 +929,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
void flushBufferUpdates() {}
|
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])
|
void setClearColor(const float rgba[4])
|
||||||
{
|
{
|
||||||
m_clearColor[0] = rgba[0];
|
m_clearColor[0] = rgba[0];
|
||||||
|
@ -1078,18 +1039,27 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
/* Update dynamic data here */
|
/* Update dynamic data here */
|
||||||
MetalDataFactoryImpl* gfxF = static_cast<MetalDataFactoryImpl*>(m_parent->getDataFactory());
|
MetalDataFactoryImpl* gfxF = static_cast<MetalDataFactoryImpl*>(m_parent->getDataFactory());
|
||||||
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
std::unique_lock<std::mutex> datalk(gfxF->m_dataMutex);
|
||||||
for (MetalData* d : gfxF->m_committedData)
|
if (gfxF->m_dataHead)
|
||||||
{
|
{
|
||||||
for (std::unique_ptr<MetalGraphicsBufferD>& b : d->m_DBufs)
|
for (BaseGraphicsData& d : *gfxF->m_dataHead)
|
||||||
b->update(m_fillBuf);
|
{
|
||||||
for (std::unique_ptr<MetalTextureD>& t : d->m_DTexs)
|
if (d.m_DBufs)
|
||||||
t->update(m_fillBuf);
|
for (IGraphicsBufferD& b : *d.m_DBufs)
|
||||||
|
static_cast<MetalGraphicsBufferD<BaseGraphicsData>&>(b).update(m_fillBuf);
|
||||||
|
if (d.m_DTexs)
|
||||||
|
for (ITextureD& t : *d.m_DTexs)
|
||||||
|
static_cast<MetalTextureD&>(t).update(m_fillBuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (MetalPool* p : gfxF->m_committedPools)
|
if (gfxF->m_poolHead)
|
||||||
{
|
{
|
||||||
for (auto& b : p->m_items)
|
for (BaseGraphicsPool& p : *gfxF->m_poolHead)
|
||||||
b->m_buf->update(m_fillBuf);
|
{
|
||||||
|
if (p.m_DBufs)
|
||||||
|
for (IGraphicsBufferD& b : *p.m_DBufs)
|
||||||
|
static_cast<MetalGraphicsBufferD<BaseGraphicsData>&>(b).update(m_fillBuf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
datalk.unlock();
|
datalk.unlock();
|
||||||
|
|
||||||
|
@ -1389,13 +1359,15 @@ IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IShaderDataBinding*
|
ObjToken<IShaderDataBinding>
|
||||||
MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
|
MetalDataFactory::Context::newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||||
IVertexFormat* vtxFormat,
|
const ObjToken<IVertexFormat>& vtxFormat,
|
||||||
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
|
const ObjToken<IGraphicsBuffer>& vbo,
|
||||||
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
|
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||||
|
const ObjToken<IGraphicsBuffer>& ibo,
|
||||||
|
size_t ubufCount, const ObjToken<IGraphicsBuffer>* ubufs, const PipelineStage* ubufStages,
|
||||||
const size_t* ubufOffs, const size_t* ubufSizes,
|
const size_t* ubufOffs, const size_t* ubufSizes,
|
||||||
size_t texCount, ITexture** texs,
|
size_t texCount, const ObjToken<ITexture>* texs,
|
||||||
const int* texBindIdxs, const bool* depthBind,
|
const int* texBindIdxs, const bool* depthBind,
|
||||||
size_t baseVert, size_t baseInst)
|
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())
|
if (m_deferredData.get())
|
||||||
Log.report(logvisor::Fatal, "nested commitTransaction usage detected");
|
Log.report(logvisor::Fatal, "nested commitTransaction usage detected");
|
||||||
|
@ -1434,62 +1406,11 @@ GraphicsDataToken MetalDataFactoryImpl::commitTransaction(const FactoryCommitFun
|
||||||
return GraphicsDataToken(this, retval);
|
return GraphicsDataToken(this, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsBufferPoolToken MetalDataFactoryImpl::newBufferPool()
|
ObjToken<IGraphicsBufferD> MetalDataFactoryImpl::newPoolBuffer(BufferUse use, size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
ObjToken<IGraphicsBufferD> pool(new BaseGraphicsPool(*this));
|
||||||
MetalPool* retval = new MetalPool;
|
|
||||||
m_committedPools.insert(retval);
|
|
||||||
return GraphicsBufferPoolToken(this, retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalDataFactoryImpl::destroyData(IGraphicsData* d)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lk(m_committedMutex);
|
|
||||||
MetalData* data = static_cast<MetalData*>(d);
|
|
||||||
m_committedData.erase(data);
|
|
||||||
data->decrement();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalDataFactoryImpl::destroyAllData()
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> 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<std::mutex> lk(m_committedMutex);
|
|
||||||
MetalPool* pool = static_cast<MetalPool*>(p);
|
|
||||||
m_committedPools.erase(pool);
|
|
||||||
delete pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
IGraphicsBufferD* MetalDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
|
|
||||||
size_t stride, size_t count)
|
|
||||||
{
|
|
||||||
MetalPool* pool = static_cast<MetalPool*>(p);
|
|
||||||
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue());
|
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue());
|
||||||
MetalPoolItem* item = new MetalPoolItem;
|
return {MetalGraphicsBufferD(pool, q, use, m_ctx, stride, count)};
|
||||||
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<MetalPool*>(p);
|
|
||||||
auto search = pool->m_items.find(static_cast<MetalPoolItem*>(buf->m_parentData));
|
|
||||||
if (search != pool->m_items.end())
|
|
||||||
{
|
|
||||||
(*search)->decrement();
|
|
||||||
pool->m_items.erase(search);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
||||||
|
|
2
logvisor
2
logvisor
|
@ -1 +1 @@
|
||||||
Subproject commit bfe0c1ccad9ee545a6ab9c0b295258c47b55da3c
|
Subproject commit f8ab0e03bae0cad2541f551350dcafb91477b007
|
Loading…
Reference in New Issue