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