OpenGL and metal rendering interface upgrades

This commit is contained in:
Jack Andersen 2017-03-13 21:02:53 -10:00
parent 73891af56a
commit 05c26a535b
14 changed files with 592 additions and 285 deletions

View File

@ -31,7 +31,8 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling)=0; ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling)=0;
}; };
}; };

View File

@ -30,7 +30,7 @@ public:
TextureFormat fmt, const void* data, size_t sz); TextureFormat fmt, const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height, ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding); size_t colorBindingCount, size_t depthBindingCount);
bool bindingNeedsVertexFormat() const {return true;} bool bindingNeedsVertexFormat() const {return true;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
@ -40,7 +40,8 @@ public:
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,
bool depthTest, bool depthWrite, CullMode culling); ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling);
IShaderDataBinding* IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,
@ -48,7 +49,9 @@ public:
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert = 0, size_t baseInst = 0); size_t texCount, ITexture** texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0);
}; };
}; };

View File

@ -32,7 +32,8 @@ 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, bool tlOrigin, bool color, bool depth)=0; virtual void resolveBindTexture(ITextureR* texture, const SWindowRect& rect,
bool tlOrigin, int bindIdx, bool color, bool depth)=0;
virtual void resolveDisplay(ITextureR* source)=0; virtual void resolveDisplay(ITextureR* source)=0;
virtual void execute()=0; virtual void execute()=0;

View File

@ -11,12 +11,22 @@ 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 struct IGraphicsBuffer
{ {
bool dynamic() const {return m_dynamic;} bool dynamic() const {return m_dynamic;}
IGraphicsData* m_parentData;
protected: protected:
bool m_dynamic; bool m_dynamic;
IGraphicsBuffer(bool dynamic) : m_dynamic(dynamic) {} IGraphicsBuffer(IGraphicsData* parent, bool dynamic)
: m_parentData(parent), m_dynamic(dynamic) {}
virtual ~IGraphicsBuffer() = default; virtual ~IGraphicsBuffer() = default;
}; };
@ -24,7 +34,7 @@ protected:
struct IGraphicsBufferS : IGraphicsBuffer struct IGraphicsBufferS : IGraphicsBuffer
{ {
protected: protected:
IGraphicsBufferS() : IGraphicsBuffer(false) {} IGraphicsBufferS(IGraphicsData* parent) : IGraphicsBuffer(parent, false) {}
}; };
/** Dynamic resource buffer for verts, indices, uniform constants */ /** Dynamic resource buffer for verts, indices, uniform constants */
@ -34,7 +44,7 @@ struct IGraphicsBufferD : IGraphicsBuffer
virtual void* map(size_t sz)=0; virtual void* map(size_t sz)=0;
virtual void unmap()=0; virtual void unmap()=0;
protected: protected:
IGraphicsBufferD() : IGraphicsBuffer(true) {} IGraphicsBufferD(IGraphicsData* parent) : IGraphicsBuffer(parent, true) {}
}; };
/** Supported buffer uses */ /** Supported buffer uses */
@ -57,9 +67,11 @@ enum class TextureType
struct ITexture struct ITexture
{ {
TextureType type() const {return m_type;} TextureType type() const {return m_type;}
IGraphicsData* m_parentData;
protected: protected:
TextureType m_type; TextureType m_type;
ITexture(TextureType type) : m_type(type) {} ITexture(IGraphicsData* parent, TextureType type)
: m_parentData(parent), m_type(type) {}
virtual ~ITexture() {} virtual ~ITexture() {}
}; };
@ -67,14 +79,14 @@ protected:
struct ITextureS : ITexture struct ITextureS : ITexture
{ {
protected: protected:
ITextureS() : ITexture(TextureType::Static) {} ITextureS(IGraphicsData* parent) : ITexture(parent, TextureType::Static) {}
}; };
/** Static-array resource buffer for array textures */ /** Static-array resource buffer for array textures */
struct ITextureSA : ITexture struct ITextureSA : ITexture
{ {
protected: protected:
ITextureSA() : ITexture(TextureType::StaticArray) {} ITextureSA(IGraphicsData* parent) : ITexture(parent, TextureType::StaticArray) {}
}; };
/** Dynamic resource buffer for textures */ /** Dynamic resource buffer for textures */
@ -84,14 +96,14 @@ struct ITextureD : ITexture
virtual void* map(size_t sz)=0; virtual void* map(size_t sz)=0;
virtual void unmap()=0; virtual void unmap()=0;
protected: protected:
ITextureD() : ITexture(TextureType::Dynamic) {} ITextureD(IGraphicsData* parent) : ITexture(parent, TextureType::Dynamic) {}
}; };
/** Resource buffer for render-target textures */ /** Resource buffer for render-target textures */
struct ITextureR : ITexture struct ITextureR : ITexture
{ {
protected: protected:
ITextureR() : ITexture(TextureType::Render) {} ITextureR(IGraphicsData* parent) : ITexture(parent, TextureType::Render) {}
}; };
/** Supported texture formats */ /** Supported texture formats */
@ -106,7 +118,12 @@ enum class TextureFormat
/** 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
{
IGraphicsData* m_parentData;
protected:
IVertexFormat(IGraphicsData* parent) : m_parentData(parent) {}
};
/** Types of vertex attributes */ /** Types of vertex attributes */
enum class VertexSemantic enum class VertexSemantic
@ -141,21 +158,18 @@ 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
{
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 {};
/** Opaque object for maintaining ownership of factory-created resources */
struct IGraphicsData {};
class GraphicsDataToken;
/** Opaque object for maintaining ownership of factory-created pool buffers */
struct IGraphicsBufferPool {};
class GraphicsBufferPoolToken;
/** Used wherever distinction of pipeline stages is needed */ /** Used wherever distinction of pipeline stages is needed */
enum class PipelineStage enum class PipelineStage
{ {
@ -178,6 +192,15 @@ enum class CullMode
Frontface Frontface
}; };
/** Used by platform shader pipeline constructors */
enum class ZTest
{
None,
LEqual, /* Flipped on Vulkan, D3D, Metal */
Greater,
Equal
};
/** Used by platform shader pipeline constructors */ /** Used by platform shader pipeline constructors */
enum class BlendFactor enum class BlendFactor
{ {
@ -234,7 +257,7 @@ struct IGraphicsDataFactory
newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0; newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0;
virtual ITextureR* virtual ITextureR*
newRenderTexture(size_t width, size_t height, newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding)=0; size_t colorBindingCount, size_t depthBindingCount)=0;
virtual bool bindingNeedsVertexFormat() const=0; virtual bool bindingNeedsVertexFormat() const=0;
virtual IVertexFormat* virtual IVertexFormat*
@ -247,28 +270,33 @@ struct IGraphicsDataFactory
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert = 0, size_t baseInst = 0)=0; size_t texCount, ITexture** texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0)=0;
IShaderDataBinding* IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat, IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages,
size_t texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0) size_t texCount, ITexture** texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0)
{ {
return newShaderDataBinding(pipeline, vtxFormat, vbo, instVbo, ibo, return newShaderDataBinding(pipeline, vtxFormat, vbo, instVbo, ibo,
ubufCount, ubufs, ubufStages, nullptr, ubufCount, ubufs, ubufStages, nullptr,
nullptr, texCount, texs, baseVert, baseInst); nullptr, texCount, texs, texBindIdx, depthBind,
baseVert, baseInst);
} }
}; };
virtual GraphicsDataToken commitTransaction(const std::function<bool(Context& ctx)>&)=0; virtual GraphicsDataToken commitTransaction(const std::function<bool(Context& ctx)>&)=0;
virtual GraphicsBufferPoolToken newBufferPool()=0; virtual GraphicsBufferPoolToken newBufferPool()=0;
virtual void destroyAllData()=0;
private: private:
friend class GraphicsDataToken; friend class GraphicsDataToken;
virtual void destroyData(IGraphicsData*)=0; virtual void destroyData(IGraphicsData*)=0;
virtual void destroyAllData()=0;
friend class GraphicsBufferPoolToken; friend class GraphicsBufferPoolToken;
virtual void destroyPool(IGraphicsBufferPool*)=0; virtual void destroyPool(IGraphicsBufferPool*)=0;

View File

@ -31,7 +31,7 @@ public:
TextureFormat fmt, const void* data, size_t sz); TextureFormat fmt, const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt); ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height, ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding); size_t colorBindCount, size_t depthBindCount);
bool bindingNeedsVertexFormat() const {return false;} bool bindingNeedsVertexFormat() const {return false;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
@ -40,7 +40,8 @@ public:
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, 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,
bool depthTest, bool depthWrite, CullMode culling); ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling);
IShaderDataBinding* IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,
@ -48,7 +49,9 @@ public:
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert = 0, size_t baseInst = 0); size_t texCount, ITexture** texs,
const int* texBindIdxs, const bool* depthBind,
size_t baseVert = 0, size_t baseInst = 0);
}; };
}; };

View File

@ -132,11 +132,12 @@ public:
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut, std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt, std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling); ZTest depthTest, bool depthWrite, CullMode culling);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling)
{ {
return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr, return newShaderPipeline(vertSource, fragSource, nullptr, nullptr, nullptr,
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling); vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, culling);

View File

@ -5,12 +5,12 @@
* binding lifetimes through rendering cycle */ * binding lifetimes through rendering cycle */
#include <atomic> #include <atomic>
#include <vector>
#include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace boo namespace boo
{ {
template <class DataImpl>
class IGraphicsDataPriv : public IGraphicsData class IGraphicsDataPriv : public IGraphicsData
{ {
std::atomic_int m_refCount = {1}; std::atomic_int m_refCount = {1};
@ -19,35 +19,50 @@ public:
void decrement() void decrement()
{ {
if (m_refCount.fetch_sub(1) == 1) if (m_refCount.fetch_sub(1) == 1)
delete static_cast<DataImpl*>(this); delete this;
} }
}; };
template <class DataImpl>
class IShaderDataBindingPriv : public IShaderDataBinding class IShaderDataBindingPriv : public IShaderDataBinding
{ {
IGraphicsDataPriv<DataImpl>* m_parent; IGraphicsDataPriv* m_parent;
std::vector<IGraphicsDataPriv*> m_depDatas;
public: public:
IShaderDataBindingPriv(IGraphicsDataPriv<DataImpl>* p) : m_parent(p) {} IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {}
class Token class Token
{ {
IGraphicsDataPriv<DataImpl>* m_data = nullptr; IGraphicsDataPriv* m_data = nullptr;
public: public:
Token() = default; Token() = default;
Token(const IShaderDataBindingPriv* p) Token(const IShaderDataBindingPriv* p)
: m_data(p->m_parent) : m_data(p->m_parent) { m_data->increment(); }
{ m_data->increment(); }
Token& operator=(const Token&) = delete; Token& operator=(const Token&) = delete;
Token(const Token&) = delete; Token(const Token&) = delete;
Token& operator=(Token&& other) Token& operator=(Token&& other)
{ m_data = other.m_data; other.m_data = nullptr; return *this; } { m_data = other.m_data; other.m_data = nullptr; return *this; }
Token(Token&& other) Token(Token&& other)
{ m_data = other.m_data; other.m_data = nullptr; } { m_data = other.m_data; other.m_data = nullptr; }
~Token() { if (m_data) m_data->decrement(); } ~Token() { if (m_data) { m_data->decrement(); } }
}; };
Token lock() const { return Token(this); } Token lock() const { return Token(this); }
~IShaderDataBindingPriv()
{
for (IGraphicsDataPriv* dep : m_depDatas)
dep->decrement();
}
protected:
void addDepData(IGraphicsData* data)
{
IGraphicsDataPriv* d = static_cast<IGraphicsDataPriv*>(data);
if (d != m_parent)
{
m_depDatas.push_back(d);
d->increment();
}
}
}; };
template <class FactoryImpl, class ShaderImpl> template <class FactoryImpl, class ShaderImpl>

View File

@ -501,7 +501,7 @@ class D3D11ShaderPipeline : public IShaderPipeline
D3D11ShareableShader::Token&& pixel, D3D11ShareableShader::Token&& pixel,
const D3D11VertexFormat* vtxFmt, const D3D11VertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
: m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
m_topology(PRIMITIVE_TABLE[int(prim)]) m_topology(PRIMITIVE_TABLE[int(prim)])
{ {
@ -538,6 +538,8 @@ class D3D11ShaderPipeline : public IShaderPipeline
blDesc.RenderTarget[0].BlendEnable = (dstFac != BlendFactor::Zero); blDesc.RenderTarget[0].BlendEnable = (dstFac != BlendFactor::Zero);
blDesc.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)]; blDesc.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)];
blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)]; blDesc.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)];
blDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
blDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState)); ThrowIfFailed(ctx->m_dev->CreateBlendState(&blDesc, &m_blState));
const auto& vertBuf = m_vert.get().m_vtxBlob; const auto& vertBuf = m_vert.get().m_vtxBlob;
@ -1008,7 +1010,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue
func(); func();
} }
float m_clearColor[4] = {0.0,0.0,0.0,1.0}; float m_clearColor[4] = {0.0,0.0,0.0,0.0};
void setClearColor(const float rgba[4]) void setClearColor(const float rgba[4])
{ {
m_clearColor[0] = rgba[0]; m_clearColor[0] = rgba[0];
@ -1336,7 +1338,7 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
{ {
XXH64_state_t hashState; XXH64_state_t hashState;
uint64_t srcHashes[2] = {}; uint64_t srcHashes[2] = {};

View File

@ -470,7 +470,6 @@ class D3D12TextureR : public ITextureR
D3D12_CLEAR_VALUE colorClear = {}; D3D12_CLEAR_VALUE colorClear = {};
colorClear.Format = DXGI_FORMAT_R8G8B8A8_UNORM; colorClear.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
colorClear.Color[3] = 1.f;
ThrowIfFailed(ctx->m_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, ThrowIfFailed(ctx->m_dev->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE,
&rtvresdesc, D3D12_RESOURCE_STATE_RENDER_TARGET, &colorClear, &rtvresdesc, D3D12_RESOURCE_STATE_RENDER_TARGET, &colorClear,
__uuidof(ID3D12Resource), &m_colorTex)); __uuidof(ID3D12Resource), &m_colorTex));
@ -654,7 +653,7 @@ class D3D12ShaderPipeline : public IShaderPipeline
D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline, D3D12ShareableShader::Token&& pixel, ID3DBlob* pipeline,
const D3D12VertexFormat* vtxFmt, const D3D12VertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
: m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)), : m_vtxFmt(vtxFmt), m_vert(std::move(vert)), m_pixel(std::move(pixel)),
m_topology(PRIMITIVE_TABLE[int(prim)]) m_topology(PRIMITIVE_TABLE[int(prim)])
{ {
@ -685,6 +684,8 @@ class D3D12ShaderPipeline : public IShaderPipeline
desc.BlendState.RenderTarget[0].BlendEnable = true; desc.BlendState.RenderTarget[0].BlendEnable = true;
desc.BlendState.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)]; desc.BlendState.RenderTarget[0].SrcBlend = BLEND_FACTOR_TABLE[int(srcFac)];
desc.BlendState.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)]; desc.BlendState.RenderTarget[0].DestBlend = BLEND_FACTOR_TABLE[int(dstFac)];
desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
} }
desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
desc.RasterizerState.FrontCounterClockwise = TRUE; desc.RasterizerState.FrontCounterClockwise = TRUE;
@ -1260,7 +1261,7 @@ struct D3D12CommandQueue : IGraphicsCommandQueue
func(); func();
} }
float m_clearColor[4] = {0.0,0.0,0.0,1.0}; float m_clearColor[4] = {0.0,0.0,0.0,0.0};
void setClearColor(const float rgba[4]) void setClearColor(const float rgba[4])
{ {
m_clearColor[0] = rgba[0]; m_clearColor[0] = rgba[0];
@ -1767,7 +1768,7 @@ public:
ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut, ComPtr<ID3DBlob>* vertBlobOut, ComPtr<ID3DBlob>* fragBlobOut,
ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt, ComPtr<ID3DBlob>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
{ {
XXH64_state_t hashState; XXH64_state_t hashState;
uint64_t srcHashes[2] = {}; uint64_t srcHashes[2] = {};

View File

@ -65,7 +65,7 @@ public:
}; };
ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData; ThreadLocalPtr<struct GLData> GLDataFactoryImpl::m_deferredData;
struct GLData : IGraphicsDataPriv<GLData> struct GLData : IGraphicsDataPriv
{ {
std::vector<std::unique_ptr<class GLShaderPipeline>> m_SPs; std::vector<std::unique_ptr<class GLShaderPipeline>> m_SPs;
std::vector<std::unique_ptr<struct GLShaderDataBinding>> m_SBinds; std::vector<std::unique_ptr<struct GLShaderDataBinding>> m_SBinds;
@ -78,9 +78,19 @@ struct GLData : IGraphicsDataPriv<GLData>
std::vector<std::unique_ptr<struct GLVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct GLVertexFormat>> m_VFmts;
}; };
struct GLPoolItem : IGraphicsDataPriv
{
std::unique_ptr<class GLGraphicsBufferD> m_buf;
};
struct GLPool : IGraphicsBufferPool struct GLPool : IGraphicsBufferPool
{ {
std::unordered_map<class GLGraphicsBufferD*, std::unique_ptr<class GLGraphicsBufferD>> m_DBufs; std::unordered_set<GLPoolItem*> m_items;
~GLPool()
{
for (auto& item : m_items)
item->decrement();
}
}; };
static const GLenum USE_TABLE[] = static const GLenum USE_TABLE[] =
@ -97,7 +107,8 @@ class GLGraphicsBufferS : public IGraphicsBufferS
friend struct GLCommandQueue; friend struct GLCommandQueue;
GLuint m_buf; GLuint m_buf;
GLenum m_target; GLenum m_target;
GLGraphicsBufferS(BufferUse use, const void* data, size_t sz) GLGraphicsBufferS(IGraphicsData* parent, BufferUse use, const void* data, size_t sz)
: IGraphicsBufferS(parent)
{ {
m_target = USE_TABLE[int(use)]; m_target = USE_TABLE[int(use)];
glGenBuffers(1, &m_buf); glGenBuffers(1, &m_buf);
@ -127,8 +138,9 @@ class GLGraphicsBufferD : public IGraphicsBufferD
std::unique_ptr<uint8_t[]> m_cpuBuf; std::unique_ptr<uint8_t[]> m_cpuBuf;
size_t m_cpuSz = 0; size_t m_cpuSz = 0;
int m_validMask = 0; int m_validMask = 0;
GLGraphicsBufferD(BufferUse use, size_t sz) GLGraphicsBufferD(IGraphicsData* parent, BufferUse use, size_t sz)
: m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) : boo::IGraphicsBufferD(parent),
m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz)
{ {
glGenBuffers(3, m_bufs); glGenBuffers(3, m_bufs);
for (int i=0 ; i<3 ; ++i) for (int i=0 ; i<3 ; ++i)
@ -154,8 +166,9 @@ public:
IGraphicsBufferS* IGraphicsBufferS*
GLDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) GLDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
GLGraphicsBufferS* retval = new GLGraphicsBufferS(use, data, stride * count); GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl::m_deferredData->m_SBufs.emplace_back(retval); GLGraphicsBufferS* retval = new GLGraphicsBufferS(d, use, data, stride * count);
d->m_SBufs.emplace_back(retval);
return retval; return retval;
} }
@ -163,8 +176,9 @@ class GLTextureS : public ITextureS
{ {
friend class GLDataFactory; friend class GLDataFactory;
GLuint m_tex; GLuint m_tex;
GLTextureS(size_t width, size_t height, size_t mips, GLTextureS(GLData* parent, size_t width, size_t height, size_t mips,
TextureFormat fmt, const void* data, size_t sz) TextureFormat fmt, const void* data, size_t sz)
: ITextureS(parent)
{ {
const uint8_t* dataIt = static_cast<const uint8_t*>(data); const uint8_t* dataIt = static_cast<const uint8_t*>(data);
glGenTextures(1, &m_tex); glGenTextures(1, &m_tex);
@ -241,8 +255,9 @@ class GLTextureSA : public ITextureSA
{ {
friend class GLDataFactory; friend class GLDataFactory;
GLuint m_tex; GLuint m_tex;
GLTextureSA(size_t width, size_t height, size_t layers, size_t mips, GLTextureSA(GLData* parent, size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, const void* data, size_t sz) TextureFormat fmt, const void* data, size_t sz)
: ITextureSA(parent)
{ {
const uint8_t* dataIt = static_cast<const uint8_t*>(data); const uint8_t* dataIt = static_cast<const uint8_t*>(data);
glGenTextures(1, &m_tex); glGenTextures(1, &m_tex);
@ -302,7 +317,7 @@ class GLTextureD : public ITextureD
size_t m_width = 0; size_t m_width = 0;
size_t m_height = 0; size_t m_height = 0;
int m_validMask = 0; int m_validMask = 0;
GLTextureD(size_t width, size_t height, TextureFormat fmt); GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt);
void update(int b); void update(int b);
public: public:
~GLTextureD(); ~GLTextureD();
@ -314,27 +329,29 @@ public:
void bind(size_t idx, int b); void bind(size_t idx, int b);
}; };
#define MAX_BIND_TEXS 4
class GLTextureR : public ITextureR class GLTextureR : public ITextureR
{ {
friend class GLDataFactory; friend class GLDataFactory;
friend struct GLCommandQueue; friend struct GLCommandQueue;
struct GLCommandQueue* m_q; struct GLCommandQueue* m_q;
GLuint m_texs[2] = {}; GLuint m_texs[2] = {};
GLuint m_bindTexs[2] = {}; GLuint m_bindTexs[2][MAX_BIND_TEXS] = {};
GLuint m_fbo = 0; GLuint m_fbo = 0;
size_t m_width = 0; size_t m_width = 0;
size_t m_height = 0; size_t m_height = 0;
size_t m_samples = 0; size_t m_samples = 0;
GLenum m_target; GLenum m_target;
GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples, GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples,
bool enableShaderColorBinding, bool enableShaderDepthBinding); size_t colorBindCount, size_t depthBindCount);
public: public:
~GLTextureR(); ~GLTextureR();
void bind(size_t idx) const void bind(size_t idx, int bindIdx, bool depth) const
{ {
glActiveTexture(GL_TEXTURE0 + idx); glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(m_target, m_bindTexs[0]); glBindTexture(m_target, m_bindTexs[depth][bindIdx]);
} }
void resize(size_t width, size_t height) void resize(size_t width, size_t height)
@ -349,15 +366,22 @@ public:
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE);
if (m_bindTexs[0]) for (int i=0 ; i<MAX_BIND_TEXS ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[0]); if (m_bindTexs[0][i])
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_RGBA, width, height, GL_FALSE); {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[0][i]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_RGBA, width, height, GL_FALSE);
}
} }
if (m_bindTexs[1])
for (int i=0 ; i<MAX_BIND_TEXS ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[1]); if (m_bindTexs[1][i])
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[1][i]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE);
}
} }
} }
else else
@ -371,15 +395,22 @@ public:
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (m_bindTexs[0]) for (int i=0 ; i<MAX_BIND_TEXS ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[0]); if (m_bindTexs[0][i])
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[0][i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
} }
if (m_bindTexs[1])
for (int i=0 ; i<MAX_BIND_TEXS ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[1]); if (m_bindTexs[1][i])
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[1][i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
}
} }
} }
} }
@ -389,8 +420,9 @@ ITextureS*
GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz) const void* data, size_t sz)
{ {
GLTextureS* retval = new GLTextureS(width, height, mips, fmt, data, sz); GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl::m_deferredData->m_STexs.emplace_back(retval); GLTextureS* retval = new GLTextureS(d, width, height, mips, fmt, data, sz);
d->m_STexs.emplace_back(retval);
return retval; return retval;
} }
@ -398,8 +430,9 @@ ITextureSA*
GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, GLDataFactory::Context::newStaticArrayTexture(size_t width, 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)
{ {
GLTextureSA* retval = new GLTextureSA(width, height, layers, mips, fmt, data, sz); GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl::m_deferredData->m_SATexs.emplace_back(retval); GLTextureSA* retval = new GLTextureSA(d, width, height, layers, mips, fmt, data, sz);
d->m_SATexs.emplace_back(retval);
return retval; return retval;
} }
@ -414,11 +447,13 @@ class GLShaderPipeline : public IShaderPipeline
GLenum m_sfactor = GL_ONE; GLenum m_sfactor = GL_ONE;
GLenum m_dfactor = GL_ZERO; GLenum m_dfactor = GL_ZERO;
GLenum m_drawPrim = GL_TRIANGLES; GLenum m_drawPrim = GL_TRIANGLES;
bool m_depthTest = true; ZTest m_depthTest = ZTest::LEqual;
bool m_depthWrite = true; bool m_depthWrite = true;
bool m_colorWrite = true;
bool m_alphaWrite = true;
CullMode m_culling; CullMode m_culling;
std::vector<GLint> m_uniLocs; std::vector<GLint> m_uniLocs;
GLShaderPipeline() = default; GLShaderPipeline(GLData* parent) : IShaderPipeline(parent) {}
public: public:
operator bool() const {return m_prog != 0;} operator bool() const {return m_prog != 0;}
~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); } ~GLShaderPipeline() { if (m_prog) glDeleteProgram(m_prog); }
@ -435,11 +470,14 @@ public:
m_drawPrim = other.m_drawPrim; m_drawPrim = other.m_drawPrim;
m_depthTest = other.m_depthTest; m_depthTest = other.m_depthTest;
m_depthWrite = other.m_depthWrite; m_depthWrite = other.m_depthWrite;
m_colorWrite = other.m_colorWrite;
m_alphaWrite = other.m_alphaWrite;
m_culling = other.m_culling; m_culling = other.m_culling;
m_uniLocs = std::move(other.m_uniLocs); m_uniLocs = std::move(other.m_uniLocs);
return *this; return *this;
} }
GLShaderPipeline(GLShaderPipeline&& other) { *this = std::move(other); } GLShaderPipeline(GLShaderPipeline&& other)
: IShaderPipeline(other.m_parentData) { *this = std::move(other); }
GLuint bind() const GLuint bind() const
{ {
@ -448,17 +486,32 @@ public:
if (m_dfactor != GL_ZERO) if (m_dfactor != GL_ZERO)
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(m_sfactor, m_dfactor); glBlendFuncSeparate(m_sfactor, m_dfactor, GL_ONE, GL_ZERO);
} }
else else
glDisable(GL_BLEND); glDisable(GL_BLEND);
if (m_depthTest) if (m_depthTest != ZTest::None)
{
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
switch (m_depthTest)
{
case ZTest::LEqual:
default:
glDepthFunc(GL_LEQUAL);
break;
case ZTest::Greater:
glDepthFunc(GL_GREATER);
break;
case ZTest::Equal:
glDepthFunc(GL_EQUAL);
break;
}
}
else else
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(m_depthWrite); glDepthMask(m_depthWrite);
glDepthFunc(GL_LEQUAL); glColorMask(m_colorWrite, m_colorWrite, m_colorWrite, m_alphaWrite);
if (m_culling != CullMode::None) if (m_culling != CullMode::None)
{ {
@ -499,10 +552,12 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline
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,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling)
{ {
GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent); GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
GLShaderPipeline shader; GLShaderPipeline shader(d);
XXH64_state_t hashState; XXH64_state_t hashState;
uint64_t hashes[2]; uint64_t hashes[2];
@ -634,11 +689,13 @@ IShaderPipeline* GLDataFactory::Context::newShaderPipeline
shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)]; shader.m_dfactor = BLEND_FACTOR_TABLE[int(dstFac)];
shader.m_depthTest = depthTest; shader.m_depthTest = depthTest;
shader.m_depthWrite = depthWrite; shader.m_depthWrite = depthWrite;
shader.m_colorWrite = colorWrite;
shader.m_alphaWrite = alphaWrite;
shader.m_culling = culling; shader.m_culling = culling;
shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)]; shader.m_drawPrim = PRIMITIVE_TABLE[int(prim)];
GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader));
GLDataFactoryImpl::m_deferredData->m_SPs.emplace_back(retval); d->m_SPs.emplace_back(retval);
return retval; return retval;
} }
@ -649,14 +706,14 @@ struct GLVertexFormat : IVertexFormat
size_t m_elementCount; size_t m_elementCount;
GLuint m_baseVert, m_baseInst; GLuint m_baseVert, m_baseInst;
std::unique_ptr<VertexElementDescriptor[]> m_elements; std::unique_ptr<VertexElementDescriptor[]> m_elements;
GLVertexFormat(GLCommandQueue* q, size_t elementCount, GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst); size_t baseVert, size_t baseInst);
~GLVertexFormat(); ~GLVertexFormat();
void bind(int idx) const {glBindVertexArray(m_vao[idx]);} void bind(int idx) const {glBindVertexArray(m_vao[idx]);}
}; };
struct GLShaderDataBinding : IShaderDataBindingPriv<GLData> struct GLShaderDataBinding : IShaderDataBindingPriv
{ {
const GLShaderPipeline* m_pipeline; const GLShaderPipeline* m_pipeline;
const GLVertexFormat* m_vtxFormat; const GLVertexFormat* m_vtxFormat;
@ -664,22 +721,32 @@ struct GLShaderDataBinding : IShaderDataBindingPriv<GLData>
std::unique_ptr<IGraphicsBuffer*[]> m_ubufs; std::unique_ptr<IGraphicsBuffer*[]> m_ubufs;
std::vector<std::pair<size_t,size_t>> m_ubufOffs; std::vector<std::pair<size_t,size_t>> m_ubufOffs;
size_t m_texCount; size_t m_texCount;
std::unique_ptr<ITexture*[]> m_texs; struct BoundTex
{
ITexture* tex;
int idx;
bool depth;
};
std::unique_ptr<BoundTex[]> m_texs;
GLShaderDataBinding(GLData* d, GLShaderDataBinding(GLData* d,
IShaderPipeline* pipeline, IShaderPipeline* pipeline,
IVertexFormat* vtxFormat, IVertexFormat* vtxFormat,
size_t ubufCount, IGraphicsBuffer** ubufs, size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes, const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs) size_t texCount, ITexture** texs,
const int* bindTexIdx,
const bool* depthBind)
: IShaderDataBindingPriv(d), : IShaderDataBindingPriv(d),
m_pipeline(static_cast<GLShaderPipeline*>(pipeline)), m_pipeline(static_cast<GLShaderPipeline*>(pipeline)),
m_vtxFormat(static_cast<GLVertexFormat*>(vtxFormat)), m_vtxFormat(static_cast<GLVertexFormat*>(vtxFormat)),
m_ubufCount(ubufCount), m_ubufCount(ubufCount),
m_ubufs(new IGraphicsBuffer*[ubufCount]), m_ubufs(new IGraphicsBuffer*[ubufCount]),
m_texCount(texCount), m_texCount(texCount),
m_texs(new ITexture*[texCount]) m_texs(new BoundTex[texCount])
{ {
addDepData(m_pipeline->m_parentData);
addDepData(m_vtxFormat->m_parentData);
if (ubufOffs && ubufSizes) if (ubufOffs && ubufSizes)
{ {
m_ubufOffs.reserve(ubufCount); m_ubufOffs.reserve(ubufCount);
@ -699,9 +766,15 @@ struct GLShaderDataBinding : IShaderDataBindingPriv<GLData>
Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i)); Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i));
#endif #endif
m_ubufs[i] = ubufs[i]; m_ubufs[i] = ubufs[i];
if (ubufs[i])
addDepData(ubufs[i]->m_parentData);
} }
for (size_t i=0 ; i<texCount ; ++i) for (size_t i=0 ; i<texCount ; ++i)
m_texs[i] = texs[i]; {
m_texs[i] = {texs[i], bindTexIdx ? bindTexIdx[i] : 0, depthBind ? depthBind[i] : false};
if (texs[i])
addDepData(texs[i]->m_parentData);
}
} }
void bind(int b) const void bind(int b) const
{ {
@ -740,22 +813,22 @@ struct GLShaderDataBinding : IShaderDataBindingPriv<GLData>
} }
for (size_t i=0 ; i<m_texCount ; ++i) for (size_t i=0 ; i<m_texCount ; ++i)
{ {
ITexture* tex = m_texs[i]; BoundTex& tex = m_texs[i];
if (tex) if (tex.tex)
{ {
switch (tex->type()) switch (tex.tex->type())
{ {
case TextureType::Dynamic: case TextureType::Dynamic:
static_cast<GLTextureD*>(tex)->bind(i, b); static_cast<GLTextureD*>(tex.tex)->bind(i, b);
break; break;
case TextureType::Static: case TextureType::Static:
static_cast<GLTextureS*>(tex)->bind(i); static_cast<GLTextureS*>(tex.tex)->bind(i);
break; break;
case TextureType::StaticArray: case TextureType::StaticArray:
static_cast<GLTextureSA*>(tex)->bind(i); static_cast<GLTextureSA*>(tex.tex)->bind(i);
break; break;
case TextureType::Render: case TextureType::Render:
static_cast<GLTextureR*>(tex)->bind(i); static_cast<GLTextureR*>(tex.tex)->bind(i, tex.idx, tex.depth);
break; break;
default: break; default: break;
} }
@ -770,11 +843,13 @@ GLDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert, size_t baseInst) size_t texCount, ITexture** texs,
const int* texBindIdx, const bool* depthBind,
size_t baseVert, size_t baseInst)
{ {
GLShaderDataBinding* retval = GLShaderDataBinding* retval =
new GLShaderDataBinding(GLDataFactoryImpl::m_deferredData.get(), pipeline, vtxFormat, ubufCount, ubufs, new GLShaderDataBinding(GLDataFactoryImpl::m_deferredData.get(), pipeline, vtxFormat, ubufCount, ubufs,
ubufOffs, ubufSizes, texCount, texs); ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind);
GLDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval); GLDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -806,7 +881,7 @@ GraphicsDataToken GLDataFactoryImpl::commitTransaction(const FactoryCommitFunc&
/* Let's go ahead and flush to ensure our data gets to the GPU /* Let's go ahead and flush to ensure our data gets to the GPU
While this isn't strictly required, some drivers might behave While this isn't strictly required, some drivers might behave
differently */ differently */
glFlush(); //glFlush();
return GraphicsDataToken(this, retval); return GraphicsDataToken(this, retval);
} }
@ -831,8 +906,8 @@ void GLDataFactoryImpl::destroyAllData()
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
for (GLData* data : m_committedData) for (GLData* data : m_committedData)
data->decrement(); data->decrement();
for (IGraphicsBufferPool* pool : m_committedPools) for (GLPool* pool : m_committedPools)
delete static_cast<GLPool*>(pool); delete pool;
m_committedData.clear(); m_committedData.clear();
m_committedPools.clear(); m_committedPools.clear();
} }
@ -849,15 +924,22 @@ IGraphicsBufferD* GLDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, Buffe
size_t stride, size_t count) size_t stride, size_t count)
{ {
GLPool* pool = static_cast<GLPool*>(p); GLPool* pool = static_cast<GLPool*>(p);
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); GLPoolItem* item = new GLPoolItem;
pool->m_DBufs.emplace(std::make_pair(retval, std::unique_ptr<GLGraphicsBufferD>(retval))); GLGraphicsBufferD* retval = new GLGraphicsBufferD(item, use, stride * count);
item->m_buf.reset(retval);
pool->m_items.emplace(item);
return retval; return retval;
} }
void GLDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool *p, IGraphicsBufferD *buf) void GLDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)
{ {
GLPool* pool = static_cast<GLPool*>(p); GLPool* pool = static_cast<GLPool*>(p);
pool->m_DBufs.erase(static_cast<GLGraphicsBufferD*>(buf)); auto search = pool->m_items.find(static_cast<GLPoolItem*>(buf->m_parentData));
if (search != pool->m_items.end())
{
(*search)->decrement();
pool->m_items.erase(search);
}
} }
static const GLint SEMANTIC_COUNT_TABLE[] = static const GLint SEMANTIC_COUNT_TABLE[] =
@ -911,6 +993,13 @@ struct GLCommandQueue : IGraphicsCommandQueue
const SystemChar* platformName() const {return _S("OpenGL");} const SystemChar* platformName() const {return _S("OpenGL");}
IGraphicsContext* m_parent = nullptr; IGraphicsContext* m_parent = nullptr;
std::mutex m_mt;
std::condition_variable m_cv;
std::mutex m_initmt;
std::condition_variable m_initcv;
std::unique_lock<std::mutex> m_initlk;
std::thread m_thr;
struct Command struct Command
{ {
enum class Op enum class Op
@ -947,8 +1036,9 @@ struct GLCommandQueue : IGraphicsCommandQueue
size_t instCount; size_t instCount;
}; };
}; };
IShaderDataBindingPriv<GLData>::Token resToken; IShaderDataBindingPriv::Token resToken;
const ITextureR* resolveTex; const ITextureR* resolveTex;
int bindIdx;
bool resolveColor : 1; bool resolveColor : 1;
bool resolveDepth : 1; bool resolveDepth : 1;
Command(Op op) : m_op(op) {} Command(Op op) : m_op(op) {}
@ -963,13 +1053,6 @@ struct GLCommandQueue : IGraphicsCommandQueue
size_t m_drawBuf = 0; size_t m_drawBuf = 0;
bool m_running = true; bool m_running = true;
std::mutex m_mt;
std::condition_variable m_cv;
std::mutex m_initmt;
std::condition_variable m_initcv;
std::unique_lock<std::mutex> m_initlk;
std::thread m_thr;
struct RenderTextureResize struct RenderTextureResize
{ {
GLTextureR* tex; GLTextureR* tex;
@ -1064,6 +1147,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
const GLubyte* version = glGetString(GL_VERSION); const GLubyte* version = glGetString(GL_VERSION);
Log.report(logvisor::Info, "OpenGL Version: %s", version); Log.report(logvisor::Info, "OpenGL Version: %s", version);
self->m_parent->postInit(); self->m_parent->postInit();
glClearColor(0.f, 0.f, 0.f, 0.f);
} }
self->m_initcv.notify_one(); self->m_initcv.notify_one();
while (self->m_running) while (self->m_running)
@ -1157,6 +1241,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
glClearColor(cmd.rgba[0], cmd.rgba[1], cmd.rgba[2], cmd.rgba[3]); glClearColor(cmd.rgba[0], cmd.rgba[1], cmd.rgba[2], cmd.rgba[3]);
break; break;
case Command::Op::ClearTarget: case Command::Op::ClearTarget:
if (cmd.flags & GL_COLOR_BUFFER_BIT)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
if (cmd.flags & GL_DEPTH_BUFFER_BIT) if (cmd.flags & GL_DEPTH_BUFFER_BIT)
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glClear(cmd.flags); glClear(cmd.flags);
@ -1181,16 +1267,16 @@ struct GLCommandQueue : IGraphicsCommandQueue
GLenum target = (tex->m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; GLenum target = (tex->m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo);
glActiveTexture(GL_TEXTURE9); glActiveTexture(GL_TEXTURE9);
if (cmd.resolveColor && tex->m_bindTexs[0]) if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
{ {
glBindTexture(target, tex->m_bindTexs[0]); glBindTexture(target, tex->m_bindTexs[0][cmd.bindIdx]);
glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]);
} }
if (cmd.resolveDepth && tex->m_bindTexs[1]) if (cmd.resolveDepth && tex->m_bindTexs[1][cmd.bindIdx])
{ {
glBindTexture(target, tex->m_bindTexs[1]); glBindTexture(target, tex->m_bindTexs[1][cmd.bindIdx]);
glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]);
@ -1230,14 +1316,20 @@ struct GLCommandQueue : IGraphicsCommandQueue
void stopRenderer() void stopRenderer()
{ {
m_running = false; if (m_running)
m_cv.notify_one(); {
m_thr.join(); m_running = false;
m_cv.notify_one();
if (m_thr.joinable())
m_thr.join();
for (int i=0 ; i<3 ; ++i)
m_cmdBufs[i].clear();
}
} }
~GLCommandQueue() ~GLCommandQueue()
{ {
if (m_running) stopRenderer(); stopRenderer();
} }
void setShaderDataBinding(IShaderDataBinding* binding) void setShaderDataBinding(IShaderDataBinding* binding)
@ -1245,7 +1337,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
std::vector<Command>& cmds = m_cmdBufs[m_fillBuf]; std::vector<Command>& cmds = m_cmdBufs[m_fillBuf];
cmds.emplace_back(Command::Op::SetShaderDataBinding); cmds.emplace_back(Command::Op::SetShaderDataBinding);
cmds.back().binding = binding; cmds.back().binding = binding;
cmds.back().resToken = static_cast<IShaderDataBindingPriv<GLData>*>(binding)->lock(); cmds.back().resToken = static_cast<IShaderDataBindingPriv*>(binding)->lock();
} }
void setRenderTarget(ITextureR* target) void setRenderTarget(ITextureR* target)
@ -1338,12 +1430,14 @@ struct GLCommandQueue : IGraphicsCommandQueue
cmds.back().instCount = instCount; cmds.back().instCount = instCount;
} }
void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth) void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin,
int bindIdx, bool color, bool depth)
{ {
GLTextureR* tex = static_cast<GLTextureR*>(texture); GLTextureR* tex = static_cast<GLTextureR*>(texture);
std::vector<Command>& cmds = m_cmdBufs[m_fillBuf]; std::vector<Command>& cmds = m_cmdBufs[m_fillBuf];
cmds.emplace_back(Command::Op::ResolveBindTexture); cmds.emplace_back(Command::Op::ResolveBindTexture);
cmds.back().resolveTex = texture; cmds.back().resolveTex = texture;
cmds.back().bindIdx = bindIdx;
cmds.back().resolveColor = color; cmds.back().resolveColor = color;
cmds.back().resolveDepth = depth; cmds.back().resolveDepth = depth;
SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height)); SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height));
@ -1421,11 +1515,11 @@ struct GLCommandQueue : IGraphicsCommandQueue
} }
for (GLPool* p : gfxF->m_committedPools) for (GLPool* p : gfxF->m_committedPools)
{ {
for (auto& b : p->m_DBufs) for (auto& b : p->m_items)
b.second->update(m_completeBuf); b->m_buf->update(m_completeBuf);
} }
datalk.unlock(); datalk.unlock();
glFlush(); //glFlush();
for (auto& p : m_pendingPosts1) for (auto& p : m_pendingPosts1)
m_pendingPosts2.push_back(std::move(p)); m_pendingPosts2.push_back(std::move(p));
@ -1476,13 +1570,14 @@ void GLGraphicsBufferD::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr si
IGraphicsBufferD* IGraphicsBufferD*
GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
{ {
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl::m_deferredData->m_DBufs.emplace_back(retval); GLGraphicsBufferD* retval = new GLGraphicsBufferD(d, use, stride * count);
d->m_DBufs.emplace_back(retval);
return retval; return retval;
} }
GLTextureD::GLTextureD(size_t width, size_t height, TextureFormat fmt) GLTextureD::GLTextureD(IGraphicsData* parent, size_t width, size_t height, TextureFormat fmt)
: m_width(width), m_height(height) : boo::ITextureD(parent), m_width(width), m_height(height)
{ {
int pxPitch = 4; int pxPitch = 4;
switch (fmt) switch (fmt)
@ -1551,20 +1646,29 @@ void GLTextureD::bind(size_t idx, int b)
ITextureD* ITextureD*
GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
{ {
GLTextureD* retval = new GLTextureD(width, height, fmt); GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl::m_deferredData->m_DTexs.emplace_back(retval); GLTextureD* retval = new GLTextureD(d, width, height, fmt);
d->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t samples, GLTextureR::GLTextureR(IGraphicsData* parent, GLCommandQueue* q, size_t width, size_t height, size_t samples,
bool enableShaderColorBinding, bool enableShaderDepthBinding) size_t colorBindingCount, size_t depthBindingCount)
: m_q(q), m_width(width), m_height(height), m_samples(samples) : boo::ITextureR(parent), m_q(q), m_width(width), m_height(height), m_samples(samples)
{ {
glGenTextures(2, m_texs); glGenTextures(2, m_texs);
if (enableShaderColorBinding) if (colorBindingCount)
glGenTextures(1, &m_bindTexs[0]); {
if (enableShaderDepthBinding) if (colorBindingCount > MAX_BIND_TEXS)
glGenTextures(1, &m_bindTexs[1]); Log.report(logvisor::Fatal, "too many color bindings for render texture");
glGenTextures(colorBindingCount, m_bindTexs[0]);
}
if (depthBindingCount)
{
if (depthBindingCount > MAX_BIND_TEXS)
Log.report(logvisor::Fatal, "too many depth bindings for render texture");
glGenTextures(depthBindingCount, m_bindTexs[1]);
}
if (samples > 1) if (samples > 1)
{ {
m_target = GL_TEXTURE_2D_MULTISAMPLE; m_target = GL_TEXTURE_2D_MULTISAMPLE;
@ -1573,14 +1677,15 @@ GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t sa
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE);
if (enableShaderColorBinding) for (int i=0 ; i<colorBindingCount ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[0]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[0][i]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE);
} }
if (enableShaderDepthBinding)
for (int i=0 ; i<depthBindingCount ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[1]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_bindTexs[1][i]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT24, width, height, GL_FALSE);
} }
} }
@ -1592,16 +1697,16 @@ GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t sa
glBindTexture(GL_TEXTURE_2D, m_texs[1]); glBindTexture(GL_TEXTURE_2D, m_texs[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
if (enableShaderColorBinding) for (int i=0 ; i<colorBindingCount ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[0]); glBindTexture(GL_TEXTURE_2D, m_bindTexs[0][i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} }
if (enableShaderDepthBinding) for (int i=0 ; i<depthBindingCount ; ++i)
{ {
glBindTexture(GL_TEXTURE_2D, m_bindTexs[1]); glBindTexture(GL_TEXTURE_2D, m_bindTexs[1][i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -1612,27 +1717,29 @@ GLTextureR::GLTextureR(GLCommandQueue* q, size_t width, size_t height, size_t sa
GLTextureR::~GLTextureR() GLTextureR::~GLTextureR()
{ {
glDeleteTextures(2, m_texs); glDeleteTextures(2, m_texs);
glDeleteTextures(2, m_bindTexs); glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
m_q->delFBO(this); m_q->delFBO(this);
} }
ITextureR* ITextureR*
GLDataFactory::Context::newRenderTexture(size_t width, size_t height, GLDataFactory::Context::newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding) size_t colorBindingCount, size_t depthBindingCount)
{ {
GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent); GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue());
GLTextureR* retval = new GLTextureR(q, width, height, factory.m_drawSamples, GLTextureR* retval = new GLTextureR(d, q, width, height, factory.m_drawSamples,
enableShaderColorBinding, enableShaderDepthBinding); colorBindingCount, depthBindingCount);
q->resizeRenderTexture(retval, width, height); q->resizeRenderTexture(retval, width, height);
GLDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval); GLDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval);
return retval; return retval;
} }
GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount, GLVertexFormat::GLVertexFormat(IGraphicsData* parent, GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst) size_t baseVert, size_t baseInst)
: m_q(q), : boo::IVertexFormat(parent),
m_q(q),
m_elementCount(elementCount), m_elementCount(elementCount),
m_elements(new VertexElementDescriptor[elementCount]), m_elements(new VertexElementDescriptor[elementCount]),
m_baseVert(baseVert), m_baseInst(baseInst) m_baseVert(baseVert), m_baseInst(baseInst)
@ -1647,10 +1754,11 @@ IVertexFormat* GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements, (size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst) size_t baseVert, size_t baseInst)
{ {
GLData* d = GLDataFactoryImpl::m_deferredData.get();
GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent); GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue());
GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements, baseVert, baseInst); GLVertexFormat* retval = new struct GLVertexFormat(d, q, elementCount, elements, baseVert, baseInst);
GLDataFactoryImpl::m_deferredData->m_VFmts.emplace_back(retval); d->m_VFmts.emplace_back(retval);
return retval; return retval;
} }

View File

@ -62,7 +62,7 @@ public:
}; };
ThreadLocalPtr<struct MetalData> MetalDataFactoryImpl::m_deferredData; ThreadLocalPtr<struct MetalData> MetalDataFactoryImpl::m_deferredData;
struct MetalData : IGraphicsDataPriv<MetalData> struct MetalData : IGraphicsDataPriv
{ {
std::vector<std::unique_ptr<class MetalShaderPipeline>> m_SPs; std::vector<std::unique_ptr<class MetalShaderPipeline>> m_SPs;
std::vector<std::unique_ptr<struct MetalShaderDataBinding>> m_SBinds; std::vector<std::unique_ptr<struct MetalShaderDataBinding>> m_SBinds;
@ -75,9 +75,19 @@ struct MetalData : IGraphicsDataPriv<MetalData>
std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts;
}; };
struct MetalPoolItem : IGraphicsDataPriv
{
std::unique_ptr<class MetalGraphicsBufferD> m_buf;
};
struct MetalPool : IGraphicsBufferPool struct MetalPool : IGraphicsBufferPool
{ {
std::unordered_map<class MetalGraphicsBufferD*, std::unique_ptr<class MetalGraphicsBufferD>> m_DBufs; std::unordered_set<MetalPoolItem*> m_items;
~MetalPool()
{
for (auto& item : m_items)
item->decrement();
}
}; };
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
@ -87,8 +97,9 @@ class MetalGraphicsBufferS : public IGraphicsBufferS
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
friend struct MetalCommandQueue; friend struct MetalCommandQueue;
MetalGraphicsBufferS(BufferUse use, MetalContext* ctx, const void* data, size_t stride, size_t count) MetalGraphicsBufferS(IGraphicsData* parent, BufferUse use, MetalContext* ctx,
: m_stride(stride), m_count(count), m_sz(stride * count) const void* data, size_t stride, size_t count)
: boo::IGraphicsBufferS(parent), m_stride(stride), m_count(count), m_sz(stride * count)
{ {
m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC]; m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC];
} }
@ -108,8 +119,9 @@ 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(MetalCommandQueue* q, BufferUse use, MetalContext* ctx, size_t stride, size_t count) MetalGraphicsBufferD(IGraphicsData* parent, MetalCommandQueue* q, BufferUse use,
: m_q(q), m_stride(stride), m_count(count), m_sz(stride * 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)
{ {
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];
@ -131,8 +143,9 @@ public:
class MetalTextureS : public ITextureS class MetalTextureS : public ITextureS
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
MetalTextureS(MetalContext* ctx, size_t width, size_t height, size_t mips, MetalTextureS(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t mips,
TextureFormat fmt, const void* data, size_t sz) TextureFormat fmt, const void* data, size_t sz)
: ITextureS(parent)
{ {
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
NSUInteger ppitchNum = 4; NSUInteger ppitchNum = 4;
@ -182,8 +195,10 @@ public:
class MetalTextureSA : public ITextureSA class MetalTextureSA : public ITextureSA
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
MetalTextureSA(MetalContext* ctx, size_t width, size_t height, size_t layers, size_t mips, MetalTextureSA(IGraphicsData* parent, MetalContext* ctx, size_t width,
size_t height, size_t layers, size_t mips,
TextureFormat fmt, const void* data, size_t sz) TextureFormat fmt, const void* data, size_t sz)
: ITextureSA(parent)
{ {
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm; MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
NSUInteger ppitch = 4; NSUInteger ppitch = 4;
@ -243,8 +258,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(MetalCommandQueue* q, MetalContext* ctx, size_t width, size_t height, TextureFormat fmt) MetalTextureD(IGraphicsData* parent, MetalCommandQueue* q, MetalContext* ctx,
: m_q(q), m_width(width), m_height(height) size_t width, size_t height, TextureFormat fmt)
: boo::ITextureD(parent), m_q(q), m_width(width), m_height(height)
{ {
MTLPixelFormat format; MTLPixelFormat format;
switch (fmt) switch (fmt)
@ -285,6 +301,8 @@ public:
void unmap(); void unmap();
}; };
#define MAX_BIND_TEXS 4
class MetalTextureR : public ITextureR class MetalTextureR : public ITextureR
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
@ -292,14 +310,20 @@ class MetalTextureR : public ITextureR
size_t m_width = 0; size_t m_width = 0;
size_t m_height = 0; size_t m_height = 0;
size_t m_samples = 0; size_t m_samples = 0;
bool m_enableShaderBindTexture; size_t m_colorBindCount;
size_t m_depthBindCount;
void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples, void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples,
bool enableShaderBindTexture) size_t colorBindCount, size_t depthBindCount)
{ {
m_width = width; m_width = width;
m_height = height; m_height = height;
if (colorBindCount > MAX_BIND_TEXS)
Log.report(logvisor::Fatal, "too many color bindings for render texture");
if (depthBindCount > MAX_BIND_TEXS)
Log.report(logvisor::Fatal, "too many depth bindings for render texture");
@autoreleasepool @autoreleasepool
{ {
MTLTextureDescriptor* desc = MTLTextureDescriptor* desc =
@ -315,15 +339,23 @@ class MetalTextureR : public ITextureR
desc.usage = MTLTextureUsageRenderTarget; desc.usage = MTLTextureUsageRenderTarget;
m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc]; m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc];
if (enableShaderBindTexture) if (colorBindCount)
{ {
desc.usage = MTLTextureUsageShaderRead; desc.usage = MTLTextureUsageShaderRead;
m_colorBindTex = [ctx->m_dev newTextureWithDescriptor:desc]; for (int i=0 ; i<colorBindCount ; ++i)
m_colorBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
} }
desc.usage = MTLTextureUsageRenderTarget; desc.usage = MTLTextureUsageRenderTarget;
desc.pixelFormat = MTLPixelFormatDepth32Float; desc.pixelFormat = MTLPixelFormatDepth32Float;
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
if (depthBindCount)
{
desc.usage = MTLTextureUsageShaderRead;
for (int i=0 ; i<depthBindCount ; ++i)
m_depthBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
}
} }
else else
{ {
@ -332,15 +364,23 @@ class MetalTextureR : public ITextureR
desc.usage = MTLTextureUsageRenderTarget; desc.usage = MTLTextureUsageRenderTarget;
m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc]; m_colorTex = [ctx->m_dev newTextureWithDescriptor:desc];
if (enableShaderBindTexture) if (colorBindCount)
{ {
desc.usage = MTLTextureUsageShaderRead; desc.usage = MTLTextureUsageShaderRead;
m_colorBindTex = [ctx->m_dev newTextureWithDescriptor:desc]; for (int i=0 ; i<colorBindCount ; ++i)
m_colorBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
} }
desc.usage = MTLTextureUsageRenderTarget; desc.usage = MTLTextureUsageRenderTarget;
desc.pixelFormat = MTLPixelFormatDepth32Float; desc.pixelFormat = MTLPixelFormatDepth32Float;
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc]; m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
if (depthBindCount)
{
desc.usage = MTLTextureUsageShaderRead;
for (int i=0 ; i<depthBindCount ; ++i)
m_depthBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
}
} }
{ {
@ -375,6 +415,7 @@ class MetalTextureR : public ITextureR
m_clearColorPassDesc.colorAttachments[0].texture = m_colorTex; m_clearColorPassDesc.colorAttachments[0].texture = m_colorTex;
m_clearColorPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; m_clearColorPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
m_clearColorPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore; m_clearColorPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
m_clearDepthPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
m_clearColorPassDesc.depthAttachment.texture = m_depthTex; m_clearColorPassDesc.depthAttachment.texture = m_depthTex;
m_clearColorPassDesc.depthAttachment.loadAction = MTLLoadActionLoad; m_clearColorPassDesc.depthAttachment.loadAction = MTLLoadActionLoad;
@ -388,6 +429,7 @@ class MetalTextureR : public ITextureR
m_clearBothPassDesc.colorAttachments[0].texture = m_colorTex; m_clearBothPassDesc.colorAttachments[0].texture = m_colorTex;
m_clearBothPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; m_clearBothPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
m_clearBothPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore; m_clearBothPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
m_clearBothPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
m_clearBothPassDesc.depthAttachment.texture = m_depthTex; m_clearBothPassDesc.depthAttachment.texture = m_depthTex;
m_clearBothPassDesc.depthAttachment.loadAction = MTLLoadActionClear; m_clearBothPassDesc.depthAttachment.loadAction = MTLLoadActionClear;
@ -397,18 +439,21 @@ class MetalTextureR : public ITextureR
} }
} }
MetalTextureR(MetalContext* ctx, size_t width, size_t height, size_t samples, MetalTextureR(IGraphicsData* parent, MetalContext* ctx, size_t width, size_t height, size_t samples,
bool enableShaderBindTexture) size_t colorBindCount, size_t depthBindCount)
: m_width(width), m_height(height), m_samples(samples), m_enableShaderBindTexture(enableShaderBindTexture) : boo::ITextureR(parent), m_width(width), m_height(height), m_samples(samples),
m_colorBindCount(colorBindCount),
m_depthBindCount(depthBindCount)
{ {
if (samples == 0) m_samples = 1; if (samples == 0) m_samples = 1;
Setup(ctx, width, height, samples, enableShaderBindTexture); Setup(ctx, width, height, samples, colorBindCount, depthBindCount);
} }
public: public:
size_t samples() const {return m_samples;} size_t samples() const {return m_samples;}
id<MTLTexture> m_colorTex; id<MTLTexture> m_colorTex;
id<MTLTexture> m_depthTex; id<MTLTexture> m_depthTex;
id<MTLTexture> m_colorBindTex; id<MTLTexture> m_colorBindTex[MAX_BIND_TEXS] = {};
id<MTLTexture> m_depthBindTex[MAX_BIND_TEXS] = {};
MTLRenderPassDescriptor* m_passDesc; MTLRenderPassDescriptor* m_passDesc;
MTLRenderPassDescriptor* m_clearDepthPassDesc; MTLRenderPassDescriptor* m_clearDepthPassDesc;
MTLRenderPassDescriptor* m_clearColorPassDesc; MTLRenderPassDescriptor* m_clearColorPassDesc;
@ -423,7 +468,7 @@ public:
height = 1; height = 1;
m_width = width; m_width = width;
m_height = height; m_height = height;
Setup(ctx, width, height, m_samples, m_enableShaderBindTexture); Setup(ctx, width, height, m_samples, m_colorBindCount, m_depthBindCount);
} }
}; };
@ -463,8 +508,8 @@ struct MetalVertexFormat : IVertexFormat
MTLVertexDescriptor* m_vdesc; MTLVertexDescriptor* m_vdesc;
size_t m_stride = 0; size_t m_stride = 0;
size_t m_instStride = 0; size_t m_instStride = 0;
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) MetalVertexFormat(IGraphicsData* parent, size_t elementCount, const VertexElementDescriptor* elements)
: m_elementCount(elementCount) : boo::IVertexFormat(parent), m_elementCount(elementCount)
{ {
for (size_t i=0 ; i<elementCount ; ++i) for (size_t i=0 ; i<elementCount ; ++i)
{ {
@ -538,10 +583,12 @@ static const MTLPrimitiveType PRIMITIVE_TABLE[] =
MTLPrimitiveTypeTriangleStrip MTLPrimitiveTypeTriangleStrip
}; };
#define COLOR_WRITE_MASK (MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue)
class MetalShaderPipeline : public IShaderPipeline class MetalShaderPipeline : public IShaderPipeline
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
friend class MetalCommandQueue; friend struct MetalCommandQueue;
friend struct MetalShaderDataBinding; friend struct MetalShaderDataBinding;
MTLCullMode m_cullMode = MTLCullModeNone; MTLCullMode m_cullMode = MTLCullModeNone;
MTLPrimitiveType m_drawPrim; MTLPrimitiveType m_drawPrim;
@ -549,13 +596,16 @@ class MetalShaderPipeline : public IShaderPipeline
MetalShareableShader::Token m_vert; MetalShareableShader::Token m_vert;
MetalShareableShader::Token m_frag; MetalShareableShader::Token m_frag;
MetalShaderPipeline(MetalContext* ctx, MetalShaderPipeline(IGraphicsData* parent,
MetalContext* ctx,
MetalShareableShader::Token&& vert, MetalShareableShader::Token&& vert,
MetalShareableShader::Token&& frag, MetalShareableShader::Token&& frag,
const MetalVertexFormat* vtxFmt, NSUInteger targetSamples, const MetalVertexFormat* vtxFmt, NSUInteger targetSamples,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, bool colorWrite,
: m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt), bool alphaWrite, CullMode culling)
: boo::IShaderPipeline(parent),
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))
{ {
switch (culling) switch (culling)
@ -578,9 +628,13 @@ class MetalShaderPipeline : public IShaderPipeline
desc.vertexDescriptor = vtxFmt->m_vdesc; desc.vertexDescriptor = vtxFmt->m_vdesc;
desc.sampleCount = targetSamples; desc.sampleCount = targetSamples;
desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm; desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
desc.colorAttachments[0].writeMask = (colorWrite ? COLOR_WRITE_MASK : 0) |
(alphaWrite ? MTLColorWriteMaskAlpha : 0);
desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero; desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)]; desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)]; desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
desc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
desc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero;
desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float; desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
NSError* err = nullptr; NSError* err = nullptr;
@ -590,8 +644,23 @@ class MetalShaderPipeline : public IShaderPipeline
[[err localizedDescription] UTF8String]); [[err localizedDescription] UTF8String]);
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new]; MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
if (depthTest) switch (depthTest)
{
case ZTest::None:
default:
dsDesc.depthCompareFunction = MTLCompareFunctionAlways;
break;
case ZTest::LEqual:
dsDesc.depthCompareFunction = MTLCompareFunctionGreaterEqual; dsDesc.depthCompareFunction = MTLCompareFunctionGreaterEqual;
break;
case ZTest::Greater:
dsDesc.depthCompareFunction = MTLCompareFunctionLess;
break;
case ZTest::Equal:
dsDesc.depthCompareFunction = MTLCompareFunctionEqual;
break;
}
dsDesc.depthWriteEnabled = depthWrite; dsDesc.depthWriteEnabled = depthWrite;
m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc]; m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc];
} }
@ -624,7 +693,23 @@ static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
} }
} }
static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx) static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx, size_t& strideOut)
{
if (buf->dynamic())
{
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
strideOut = cbuf->m_stride;
return cbuf->m_bufs[idx];
}
else
{
const MetalGraphicsBufferS* cbuf = static_cast<const MetalGraphicsBufferS*>(buf);
strideOut = cbuf->m_stride;
return cbuf->m_buf;
}
}
static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx, int bindIdx, bool depth)
{ {
switch (tex->type()) switch (tex->type())
{ {
@ -646,14 +731,14 @@ static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx)
case TextureType::Render: case TextureType::Render:
{ {
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex); const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex);
return ctex->m_colorBindTex; return depth ? ctex->m_depthBindTex[bindIdx] : ctex->m_colorBindTex[bindIdx];
} }
default: break; default: break;
} }
return nullptr; return nullptr;
} }
struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData> struct MetalShaderDataBinding : IShaderDataBindingPriv
{ {
MetalShaderPipeline* m_pipeline; MetalShaderPipeline* m_pipeline;
IGraphicsBuffer* m_vbuf; IGraphicsBuffer* m_vbuf;
@ -664,7 +749,13 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
std::unique_ptr<size_t[]> m_ubufOffs; std::unique_ptr<size_t[]> m_ubufOffs;
std::unique_ptr<bool[]> m_fubufs; std::unique_ptr<bool[]> m_fubufs;
size_t m_texCount; size_t m_texCount;
std::unique_ptr<ITexture*[]> m_texs; struct BoundTex
{
ITexture* tex;
int idx;
bool depth;
};
std::unique_ptr<BoundTex[]> m_texs;
size_t m_baseVert; size_t m_baseVert;
size_t m_baseInst; size_t m_baseInst;
@ -674,7 +765,9 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf, IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert, size_t baseInst) size_t texCount, ITexture** texs,
const int* texBindIdxs, const bool* depthBind,
size_t baseVert, size_t baseInst)
: IShaderDataBindingPriv(d), : IShaderDataBindingPriv(d),
m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)), m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)),
m_vbuf(vbuf), m_vbuf(vbuf),
@ -683,10 +776,12 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
m_ubufCount(ubufCount), m_ubufCount(ubufCount),
m_ubufs(new IGraphicsBuffer*[ubufCount]), m_ubufs(new IGraphicsBuffer*[ubufCount]),
m_texCount(texCount), m_texCount(texCount),
m_texs(new ITexture*[texCount]), m_texs(new BoundTex[texCount]),
m_baseVert(baseVert), m_baseVert(baseVert),
m_baseInst(baseInst) m_baseInst(baseInst)
{ {
addDepData(m_pipeline->m_parentData);
if (ubufCount && ubufStages) if (ubufCount && ubufStages)
{ {
m_fubufs.reset(new bool[ubufCount]); m_fubufs.reset(new bool[ubufCount]);
@ -713,10 +808,14 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i)); Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i));
#endif #endif
m_ubufs[i] = ubufs[i]; m_ubufs[i] = ubufs[i];
if (ubufs[i])
addDepData(ubufs[i]->m_parentData);
} }
for (size_t i=0 ; i<texCount ; ++i) for (size_t i=0 ; i<texCount ; ++i)
{ {
m_texs[i] = texs[i]; m_texs[i] = {texs[i], texBindIdxs ? texBindIdxs[i] : 0, depthBind ? depthBind[i] : false};
if (texs[i])
addDepData(texs[i]->m_parentData);
} }
} }
@ -724,12 +823,17 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
{ {
m_pipeline->bind(enc); m_pipeline->bind(enc);
size_t stride;
if (m_vbuf) if (m_vbuf)
[enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b) {
offset:m_pipeline->m_vtxFmt->m_stride * m_baseVert atIndex:0]; id<MTLBuffer> buf = GetBufferGPUResource(m_vbuf, b, stride);
[enc setVertexBuffer:buf offset:stride * m_baseVert atIndex:0];
}
if (m_instVbo) if (m_instVbo)
[enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b) {
offset:m_pipeline->m_vtxFmt->m_instStride * m_baseInst atIndex:1]; id<MTLBuffer> buf = GetBufferGPUResource(m_instVbo, b, stride);
[enc setVertexBuffer:buf offset:stride * m_baseInst atIndex:1];
}
if (m_ubufOffs) if (m_ubufOffs)
for (size_t i=0 ; i<m_ubufCount ; ++i) for (size_t i=0 ; i<m_ubufCount ; ++i)
{ {
@ -747,8 +851,8 @@ struct MetalShaderDataBinding : IShaderDataBindingPriv<MetalData>
[enc setVertexBuffer:GetBufferGPUResource(m_ubufs[i], b) offset:0 atIndex:i+2]; [enc setVertexBuffer:GetBufferGPUResource(m_ubufs[i], b) offset:0 atIndex:i+2];
} }
for (size_t i=0 ; i<m_texCount ; ++i) for (size_t i=0 ; i<m_texCount ; ++i)
if (m_texs[i]) if (m_texs[i].tex)
[enc setFragmentTexture:GetTextureGPUResource(m_texs[i], b) atIndex:i]; [enc setFragmentTexture:GetTextureGPUResource(m_texs[i].tex, b, m_texs[i].idx, m_texs[i].depth) atIndex:i];
} }
}; };
@ -801,9 +905,9 @@ struct MetalCommandQueue : IGraphicsCommandQueue
void _setRenderTarget(ITextureR* target, bool clearColor, bool clearDepth) void _setRenderTarget(ITextureR* target, bool clearColor, bool clearDepth)
{ {
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target); MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
[m_enc endEncoding];
@autoreleasepool @autoreleasepool
{ {
[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];
else if (clearColor) else if (clearColor)
@ -865,7 +969,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
void flushBufferUpdates() {} void flushBufferUpdates() {}
float m_clearColor[4] = {0.0,0.0,0.0,1.0}; float m_clearColor[4] = {0.0,0.0,0.0,0.0};
void setClearColor(const float rgba[4]) void setClearColor(const float rgba[4])
{ {
m_clearColor[0] = rgba[0]; m_clearColor[0] = rgba[0];
@ -911,36 +1015,53 @@ struct MetalCommandQueue : IGraphicsCommandQueue
instanceCount:instCount]; instanceCount:instCount];
} }
void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin, bool color, bool depth) void resolveBindTexture(ITextureR* texture, const SWindowRect& rect, bool tlOrigin,
int bindIdx, bool color, bool depth)
{ {
MetalTextureR* tex = static_cast<MetalTextureR*>(texture); MetalTextureR* tex = static_cast<MetalTextureR*>(texture);
if (color && tex->m_enableShaderBindTexture) @autoreleasepool
{ {
[m_enc endEncoding]; [m_enc endEncoding];
@autoreleasepool SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height));
NSUInteger y = tlOrigin ? intersectRect.location[1] : int(tex->m_height) -
intersectRect.location[1] - intersectRect.size[1];
MTLOrigin origin = {NSUInteger(intersectRect.location[0]), y, 0};
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
if (color && tex->m_colorBindTex[bindIdx])
{ {
SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height));
NSUInteger y = tlOrigin ? intersectRect.location[1] : int(tex->m_height) - intersectRect.location[1] - intersectRect.size[1];
MTLOrigin origin = {NSUInteger(intersectRect.location[0]), y, 0};
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
[blitEnc copyFromTexture:tex->m_colorTex [blitEnc copyFromTexture:tex->m_colorTex
sourceSlice:0 sourceSlice:0
sourceLevel:0 sourceLevel:0
sourceOrigin:origin sourceOrigin:origin
sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1) sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1)
toTexture:tex->m_colorBindTex toTexture:tex->m_colorBindTex[bindIdx]
destinationSlice:0 destinationSlice:0
destinationLevel:0 destinationLevel:0
destinationOrigin:origin]; destinationOrigin:origin];
[blitEnc endEncoding];
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_passDesc];
[m_enc setFrontFacingWinding:MTLWindingCounterClockwise];
if (m_boundVp.width || m_boundVp.height)
[m_enc setViewport:m_boundVp];
if (m_boundScissor.width || m_boundScissor.height)
[m_enc setScissorRect:m_boundScissor];
} }
if (depth && tex->m_depthBindTex[bindIdx])
{
[blitEnc copyFromTexture:tex->m_depthTex
sourceSlice:0
sourceLevel:0
sourceOrigin:origin
sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1)
toTexture:tex->m_depthBindTex[bindIdx]
destinationSlice:0
destinationLevel:0
destinationOrigin:origin];
}
[blitEnc endEncoding];
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_passDesc];
[m_enc setFrontFacingWinding:MTLWindingCounterClockwise];
if (m_boundVp.width || m_boundVp.height)
[m_enc setViewport:m_boundVp];
if (m_boundScissor.width || m_boundScissor.height)
[m_enc setScissorRect:m_boundScissor];
} }
} }
@ -968,8 +1089,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue
} }
for (MetalPool* p : gfxF->m_committedPools) for (MetalPool* p : gfxF->m_committedPools)
{ {
for (auto& b : p->m_DBufs) for (auto& b : p->m_items)
b.second->update(m_fillBuf); b->m_buf->update(m_fillBuf);
} }
datalk.unlock(); datalk.unlock();
@ -999,38 +1120,35 @@ struct MetalCommandQueue : IGraphicsCommandQueue
if (m_needsDisplay) if (m_needsDisplay)
{ {
MetalContext::Window& w = m_ctx->m_windows[m_parentWindow]; MetalContext::Window& w = m_ctx->m_windows[m_parentWindow];
@autoreleasepool
{ {
std::unique_lock<std::mutex> lk(w.m_resizeLock);
if (w.m_needsResize)
{ {
std::unique_lock<std::mutex> lk(w.m_resizeLock); w.m_metalLayer.drawableSize = w.m_size;
if (w.m_needsResize) w.m_needsResize = NO;
{ m_needsDisplay = nullptr;
w.m_metalLayer.drawableSize = w.m_size; return;
w.m_needsResize = NO;
m_needsDisplay = nullptr;
return;
}
} }
id<CAMetalDrawable> drawable = [w.m_metalLayer nextDrawable]; }
if (drawable) id<CAMetalDrawable> drawable = [w.m_metalLayer nextDrawable];
if (drawable)
{
id<MTLTexture> dest = drawable.texture;
if (m_needsDisplay->m_colorTex.width == dest.width &&
m_needsDisplay->m_colorTex.height == dest.height)
{ {
id<MTLTexture> dest = drawable.texture; id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
if (m_needsDisplay->m_colorTex.width == dest.width && [blitEnc copyFromTexture:m_needsDisplay->m_colorTex
m_needsDisplay->m_colorTex.height == dest.height) sourceSlice:0
{ sourceLevel:0
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder]; sourceOrigin:MTLOriginMake(0, 0, 0)
[blitEnc copyFromTexture:m_needsDisplay->m_colorTex sourceSize:MTLSizeMake(dest.width, dest.height, 1)
sourceSlice:0 toTexture:dest
sourceLevel:0 destinationSlice:0
sourceOrigin:MTLOriginMake(0, 0, 0) destinationLevel:0
sourceSize:MTLSizeMake(dest.width, dest.height, 1) destinationOrigin:MTLOriginMake(0, 0, 0)];
toTexture:dest [blitEnc endEncoding];
destinationSlice:0 [m_cmdBuf presentDrawable:drawable];
destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)];
[blitEnc endEncoding];
[m_cmdBuf presentDrawable:drawable];
}
} }
} }
m_needsDisplay = nullptr; m_needsDisplay = nullptr;
@ -1107,66 +1225,76 @@ MetalDataFactoryImpl::MetalDataFactoryImpl(IGraphicsContext* parent, MetalContex
IGraphicsBufferS* MetalDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) IGraphicsBufferS* MetalDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(use, factory.m_ctx, data, stride, count); MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(d, use, factory.m_ctx, data, stride, count);
MetalDataFactoryImpl::m_deferredData->m_SBufs.emplace_back(retval); d->m_SBufs.emplace_back(retval);
return retval; return retval;
} }
IGraphicsBufferD* MetalDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) IGraphicsBufferD* MetalDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(factory.m_parent->getCommandQueue()); MetalCommandQueue* q = static_cast<MetalCommandQueue*>(factory.m_parent->getCommandQueue());
MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, factory.m_ctx, stride, count); MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(d, q, use, factory.m_ctx, stride, count);
MetalDataFactoryImpl::m_deferredData->m_DBufs.emplace_back(retval); d->m_DBufs.emplace_back(retval);
return retval; return retval;
} }
ITextureS* MetalDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, ITextureS* MetalDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz) const void* data, size_t sz)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalTextureS* retval = new MetalTextureS(factory.m_ctx, width, height, mips, fmt, data, sz); MetalTextureS* retval = new MetalTextureS(d, factory.m_ctx, width, height, mips, fmt, data, sz);
MetalDataFactoryImpl::m_deferredData->m_STexs.emplace_back(retval); d->m_STexs.emplace_back(retval);
return retval; return retval;
} }
ITextureSA* MetalDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, size_t mips, ITextureSA* MetalDataFactory::Context::newStaticArrayTexture(size_t width, 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)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalTextureSA* retval = new MetalTextureSA(factory.m_ctx, width, height, layers, mips, fmt, data, sz); MetalTextureSA* retval = new MetalTextureSA(d, factory.m_ctx, width, height, layers, mips, fmt, data, sz);
MetalDataFactoryImpl::m_deferredData->m_SATexs.emplace_back(retval); d->m_SATexs.emplace_back(retval);
return retval; return retval;
} }
ITextureD* MetalDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) ITextureD* MetalDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(factory.m_parent->getCommandQueue()); MetalCommandQueue* q = static_cast<MetalCommandQueue*>(factory.m_parent->getCommandQueue());
MetalTextureD* retval = new MetalTextureD(q, factory.m_ctx, width, height, fmt); MetalTextureD* retval = new MetalTextureD(d, q, factory.m_ctx, width, height, fmt);
MetalDataFactoryImpl::m_deferredData->m_DTexs.emplace_back(retval); d->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
ITextureR* MetalDataFactory::Context::newRenderTexture(size_t width, size_t height, ITextureR* MetalDataFactory::Context::newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding) size_t colorBindCount, size_t depthBindCount)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalTextureR* retval = new MetalTextureR(factory.m_ctx, width, height, factory.m_sampleCount, enableShaderColorBinding); MetalTextureR* retval = new MetalTextureR(d, factory.m_ctx, width, height, factory.m_sampleCount,
MetalDataFactoryImpl::m_deferredData->m_RTexs.emplace_back(retval); colorBindCount, depthBindCount);
d->m_RTexs.emplace_back(retval);
return retval; return retval;
} }
IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements, IVertexFormat* MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst) size_t baseVert, size_t baseInst)
{ {
MetalVertexFormat* retval = new struct MetalVertexFormat(elementCount, elements); MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl::m_deferredData->m_VFmts.emplace_back(retval); MetalVertexFormat* retval = new struct MetalVertexFormat(d, elementCount, elements);
d->m_VFmts.emplace_back(retval);
return retval; return retval;
} }
IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* MetalDataFactory::Context::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,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling)
{ {
MetalData* d = MetalDataFactoryImpl::m_deferredData.get();
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MTLCompileOptions* compOpts = [MTLCompileOptions new]; MTLCompileOptions* compOpts = [MTLCompileOptions new];
compOpts.languageVersion = MTLLanguageVersion1_1; compOpts.languageVersion = MTLLanguageVersion1_1;
@ -1228,10 +1356,11 @@ IShaderPipeline* MetalDataFactory::Context::newShaderPipeline(const char* vertSo
fragShader = it->second->lock(); fragShader = it->second->lock();
} }
MetalShaderPipeline* retval = new MetalShaderPipeline(factory.m_ctx, std::move(vertShader), std::move(fragShader), MetalShaderPipeline* retval = new MetalShaderPipeline(d, factory.m_ctx, std::move(vertShader), std::move(fragShader),
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples, static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
srcFac, dstFac, prim, depthTest, depthWrite, culling); srcFac, dstFac, prim, depthTest, depthWrite,
MetalDataFactoryImpl::m_deferredData->m_SPs.emplace_back(retval); colorWrite, alphaWrite, culling);
d->m_SPs.emplace_back(retval);
return retval; return retval;
} }
@ -1241,14 +1370,17 @@ MetalDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf, IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, const PipelineStage* ubufStages, size_t ubufCount, 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 baseVert, size_t baseInst) size_t texCount, ITexture** texs,
const int* texBindIdxs, const bool* depthBind,
size_t baseVert, size_t baseInst)
{ {
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MetalShaderDataBinding* retval = MetalShaderDataBinding* retval =
new MetalShaderDataBinding(MetalDataFactoryImpl::m_deferredData.get(), new MetalShaderDataBinding(MetalDataFactoryImpl::m_deferredData.get(),
factory.m_ctx, pipeline, vbuf, instVbo, ibuf, factory.m_ctx, pipeline, vbuf, instVbo, ibuf,
ubufCount, ubufs, ubufStages, ubufOffs, ubufCount, ubufs, ubufStages, ubufOffs,
ubufSizes, texCount, texs, baseVert, baseInst); ubufSizes, texCount, texs, texBindIdxs,
depthBind, baseVert, baseInst);
MetalDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval); MetalDataFactoryImpl::m_deferredData->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -1295,8 +1427,8 @@ void MetalDataFactoryImpl::destroyAllData()
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
for (MetalData* data : m_committedData) for (MetalData* data : m_committedData)
data->decrement(); data->decrement();
for (IGraphicsBufferPool* pool : m_committedPools) for (MetalPool* pool : m_committedPools)
delete static_cast<MetalPool*>(pool); delete pool;
m_committedData.clear(); m_committedData.clear();
m_committedPools.clear(); m_committedPools.clear();
} }
@ -1314,15 +1446,22 @@ IGraphicsBufferD* MetalDataFactoryImpl::newPoolBuffer(IGraphicsBufferPool* p, Bu
{ {
MetalPool* pool = static_cast<MetalPool*>(p); MetalPool* pool = static_cast<MetalPool*>(p);
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue()); MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue());
MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, m_ctx, stride, count); MetalPoolItem* item = new MetalPoolItem;
pool->m_DBufs.emplace(std::make_pair(retval, std::unique_ptr<MetalGraphicsBufferD>(retval))); MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(item, q, use, m_ctx, stride, count);
item->m_buf.reset(retval);
pool->m_items.emplace(item);
return retval; return retval;
} }
void MetalDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf) void MetalDataFactoryImpl::deletePoolBuffer(IGraphicsBufferPool* p, IGraphicsBufferD* buf)
{ {
MetalPool* pool = static_cast<MetalPool*>(p); MetalPool* pool = static_cast<MetalPool*>(p);
pool->m_DBufs.erase(static_cast<MetalGraphicsBufferD*>(buf)); 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,

View File

@ -1841,7 +1841,7 @@ class VulkanShaderPipeline : public IShaderPipeline
VkPipelineCache pipelineCache, VkPipelineCache pipelineCache,
const VulkanVertexFormat* vtxFmt, const VulkanVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
: m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt), : m_ctx(ctx), m_pipelineCache(pipelineCache), m_vtxFmt(vtxFmt),
m_vert(std::move(vert)), m_frag(std::move(frag)) m_vert(std::move(vert)), m_frag(std::move(frag))
{ {
@ -2509,7 +2509,7 @@ struct VulkanCommandQueue : IGraphicsCommandQueue
func(); func();
} }
float m_clearColor[4] = {0.0,0.0,0.0,1.0}; float m_clearColor[4] = {0.0,0.0,0.0,0.0};
void setClearColor(const float rgba[4]) void setClearColor(const float rgba[4])
{ {
m_clearColor[0] = rgba[0]; m_clearColor[0] = rgba[0];
@ -3081,7 +3081,7 @@ IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut, std::vector<unsigned int>* vertBlobOut, std::vector<unsigned int>* fragBlobOut,
std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt, std::vector<unsigned char>* pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, CullMode culling) ZTest depthTest, bool depthWrite, CullMode culling)
{ {
VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent); VulkanDataFactoryImpl& factory = static_cast<VulkanDataFactoryImpl&>(m_parent);

View File

@ -214,8 +214,10 @@ public:
~GraphicsContextCocoaGL() ~GraphicsContextCocoaGL()
{ {
delete m_dataFactory; m_commandQueue->stopRenderer();
m_dataFactory->destroyAllData();
delete m_commandQueue; delete m_commandQueue;
delete m_dataFactory;
} }
void _setCallback(IWindowCallback* cb) void _setCallback(IWindowCallback* cb)
@ -370,8 +372,10 @@ public:
~GraphicsContextCocoaMetal() ~GraphicsContextCocoaMetal()
{ {
delete m_dataFactory; m_commandQueue->stopRenderer();
m_dataFactory->destroyAllData();
delete m_commandQueue; delete m_commandQueue;
delete m_dataFactory;
m_metalCtx->m_windows.erase(m_parentWindow); m_metalCtx->m_windows.erase(m_parentWindow);
} }

View File

@ -308,7 +308,7 @@ struct TestApplicationCallback : IApplicationCallback
pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr, pipeline = glF.newShaderPipeline(VS, FS, 1, &texName, 0, nullptr,
BlendFactor::One, BlendFactor::Zero, BlendFactor::One, BlendFactor::Zero,
Primitive::TriStrips, true, true, CullMode::None); Primitive::TriStrips, boo::ZTest::LEqual, true, true, false, CullMode::None);
} }
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
else if (plat == IGraphicsDataFactory::Platform::Vulkan) else if (plat == IGraphicsDataFactory::Platform::Vulkan)
@ -403,13 +403,14 @@ struct TestApplicationCallback : IApplicationCallback
pipeline = metalF.newShaderPipeline(VS, FS, vfmt, 1, pipeline = metalF.newShaderPipeline(VS, FS, vfmt, 1,
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, boo::CullMode::None); boo::ZTest::LEqual, true, true, true, boo::CullMode::None);
} }
#endif #endif
/* Make shader data binding */ /* Make shader data binding */
self->m_binding = self->m_binding =
ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, nullptr, 1, &texture); ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, nullptr,
1, &texture, nullptr, nullptr);
return true; return true;
}); });