macOS HIDPI fixes; buffer pools

This commit is contained in:
Jack Andersen 2016-12-09 16:31:50 -10:00
parent 4c0c01f84f
commit fa45c6750a
6 changed files with 225 additions and 41 deletions

View File

@ -19,9 +19,13 @@ class GLDataFactory : public IGraphicsDataFactory
uint32_t m_drawSamples; uint32_t m_drawSamples;
static ThreadLocalPtr<struct GLData> m_deferredData; static ThreadLocalPtr<struct GLData> m_deferredData;
std::unordered_set<struct GLData*> m_committedData; std::unordered_set<struct GLData*> m_committedData;
std::unordered_set<struct GLPool*> m_committedPools;
std::mutex m_committedMutex; std::mutex m_committedMutex;
void destroyData(IGraphicsData*); void destroyData(IGraphicsData*);
void destroyAllData(); void destroyAllData();
void destroyPool(IGraphicsBufferPool*);
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count);
public: public:
GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples); GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples);
~GLDataFactory() {destroyAllData();} ~GLDataFactory() {destroyAllData();}
@ -50,7 +54,8 @@ public:
bool enableShaderColorBinding, bool enableShaderDepthBinding); bool enableShaderColorBinding, bool enableShaderDepthBinding);
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,
size_t baseVert = 0, size_t baseInst = 0);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
size_t texCount, const char** texNames, size_t texCount, const char** texNames,
@ -64,10 +69,11 @@ 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 texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0);
}; };
GraphicsDataToken commitTransaction(const FactoryCommitFunc&); GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
GraphicsBufferPoolToken newBufferPool();
}; };
} }

View File

@ -152,6 +152,10 @@ struct IShaderDataBinding {};
struct IGraphicsData {}; struct IGraphicsData {};
class GraphicsDataToken; 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
{ {
@ -226,7 +230,8 @@ struct IGraphicsDataFactory
virtual bool bindingNeedsVertexFormat() const=0; virtual bool bindingNeedsVertexFormat() const=0;
virtual IVertexFormat* virtual IVertexFormat*
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0; newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert = 0, size_t baseInst = 0)=0;
virtual IShaderDataBinding* virtual IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline, newShaderDataBinding(IShaderPipeline* pipeline,
@ -234,32 +239,39 @@ 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)=0; size_t texCount, ITexture** texs, 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 texCount, ITexture** texs, 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, nullptr, texCount, texs); ubufCount, ubufs, ubufStages, nullptr,
nullptr, texCount, texs, 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;
private: private:
friend class GraphicsDataToken; friend class GraphicsDataToken;
virtual void destroyData(IGraphicsData*)=0; virtual void destroyData(IGraphicsData*)=0;
virtual void destroyAllData()=0; virtual void destroyAllData()=0;
friend class GraphicsBufferPoolToken;
virtual void destroyPool(IGraphicsBufferPool*)=0;
virtual IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count)=0;
}; };
using FactoryCommitFunc = std::function<bool(IGraphicsDataFactory::Context& ctx)>; using FactoryCommitFunc = std::function<bool(IGraphicsDataFactory::Context& ctx)>;
/** Ownership token for maintaining lifetime of factory-created resources /** Ownership token for maintaining lifetime of factory-created resources.
* deletion of this token triggers mass-deallocation of the factory's * Deletion of this token triggers mass-deallocation of the factory's
* IGraphicsData (please don't delete and draw contained resources in the same frame). */ * IGraphicsData (please don't delete and draw contained resources in the same frame). */
class GraphicsDataToken class GraphicsDataToken
{ {
@ -305,6 +317,59 @@ public:
operator bool() const {return m_factory && m_data;} operator bool() const {return m_factory && m_data;}
}; };
/** Ownership token for maintaining lifetimes of an appendable list of dynamic buffers.
* Deletion of this token triggers mass-deallocation of the IGraphicsBufferPool
* (please don't delete and draw contained resources in the same frame). */
class GraphicsBufferPoolToken
{
friend class GLDataFactory;
friend class D3D12DataFactory;
friend class D3D11DataFactory;
friend class MetalDataFactory;
friend class VulkanDataFactory;
IGraphicsDataFactory* m_factory = nullptr;
IGraphicsBufferPool* m_pool = nullptr;
GraphicsBufferPoolToken(IGraphicsDataFactory* factory, IGraphicsBufferPool* pool)
: m_factory(factory), m_pool(pool) {}
public:
void doDestroy()
{
if (m_factory && m_pool)
{
m_factory->destroyPool(m_pool);
m_factory = nullptr;
m_pool = nullptr;
}
}
GraphicsBufferPoolToken() = default;
GraphicsBufferPoolToken(const GraphicsBufferPoolToken& other) = delete;
GraphicsBufferPoolToken(GraphicsBufferPoolToken&& other)
{
m_factory = other.m_factory;
other.m_factory = nullptr;
m_pool = other.m_pool;
other.m_pool = nullptr;
}
GraphicsBufferPoolToken& operator=(const GraphicsBufferPoolToken& other) = delete;
GraphicsBufferPoolToken& operator=(GraphicsBufferPoolToken&& other)
{
doDestroy();
m_factory = other.m_factory;
other.m_factory = nullptr;
m_pool = other.m_pool;
other.m_pool = nullptr;
return *this;
}
~GraphicsBufferPoolToken() {doDestroy();}
operator bool() const {return m_factory && m_pool;}
IGraphicsBufferD* newPoolBuffer(BufferUse use,
size_t stride, size_t count)
{
return m_factory->newPoolBuffer(m_pool, use, stride, count);
}
};
} }
#endif // IGFXDATAFACTORY_HPP #endif // IGFXDATAFACTORY_HPP

View File

@ -21,12 +21,16 @@ class MetalDataFactory : public IGraphicsDataFactory
IGraphicsContext* m_parent; IGraphicsContext* m_parent;
static ThreadLocalPtr<struct MetalData> m_deferredData; static ThreadLocalPtr<struct MetalData> m_deferredData;
std::unordered_set<struct MetalData*> m_committedData; std::unordered_set<struct MetalData*> m_committedData;
std::unordered_set<struct MetalPool*> m_committedPools;
std::mutex m_committedMutex; std::mutex m_committedMutex;
struct MetalContext* m_ctx; struct MetalContext* m_ctx;
uint32_t m_sampleCount; uint32_t m_sampleCount;
void destroyData(IGraphicsData*); void destroyData(IGraphicsData*);
void destroyAllData(); void destroyAllData();
void destroyPool(IGraphicsBufferPool*);
IGraphicsBufferD* newPoolBuffer(IGraphicsBufferPool* pool, BufferUse use,
size_t stride, size_t count);
public: public:
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount); MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount);
~MetalDataFactory() {} ~MetalDataFactory() {}
@ -55,7 +59,8 @@ public:
bool enableShaderColorBinding, bool enableShaderDepthBinding); bool enableShaderColorBinding, bool enableShaderDepthBinding);
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,
size_t baseVert = 0, size_t baseInst = 0);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, IVertexFormat* vtxFmt, unsigned targetSamples,
@ -68,10 +73,11 @@ 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 texCount, ITexture** texs, size_t baseVert = 0, size_t baseInst = 0);
}; };
virtual GraphicsDataToken commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&); GraphicsDataToken commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>&);
GraphicsBufferPoolToken newBufferPool();
}; };
} }

View File

@ -30,6 +30,11 @@ struct GLData : IGraphicsData
std::vector<std::unique_ptr<struct GLVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct GLVertexFormat>> m_VFmts;
}; };
struct GLPool : IGraphicsBufferPool
{
std::vector<std::unique_ptr<class GLGraphicsBufferD>> m_DBufs;
};
static const GLenum USE_TABLE[] = static const GLenum USE_TABLE[] =
{ {
GL_INVALID_ENUM, GL_INVALID_ENUM,
@ -533,9 +538,11 @@ struct GLVertexFormat : IVertexFormat
GLCommandQueue* m_q; GLCommandQueue* m_q;
GLuint m_vao[3] = {}; GLuint m_vao[3] = {};
size_t m_elementCount; size_t m_elementCount;
GLuint m_baseVert, m_baseInst;
std::unique_ptr<VertexElementDescriptor[]> m_elements; std::unique_ptr<VertexElementDescriptor[]> m_elements;
GLVertexFormat(GLCommandQueue* q, size_t elementCount, GLVertexFormat(GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements); const VertexElementDescriptor* elements,
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]);}
}; };
@ -652,10 +659,11 @@ 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 texCount, ITexture** texs, size_t baseVert, size_t baseInst)
{ {
GLShaderDataBinding* retval = GLShaderDataBinding* retval =
new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs); new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs,
ubufOffs, ubufSizes, texCount, texs);
m_deferredData->m_SBinds.emplace_back(retval); m_deferredData->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -690,6 +698,14 @@ GraphicsDataToken GLDataFactory::commitTransaction(const FactoryCommitFunc& tran
return GraphicsDataToken(this, retval); return GraphicsDataToken(this, retval);
} }
GraphicsBufferPoolToken GLDataFactory::newBufferPool()
{
std::unique_lock<std::mutex> lk(m_committedMutex);
GLPool* retval = new GLPool;
m_committedPools.insert(retval);
return GraphicsBufferPoolToken(this, retval);
}
void GLDataFactory::destroyData(IGraphicsData* d) void GLDataFactory::destroyData(IGraphicsData* d)
{ {
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
@ -703,7 +719,27 @@ void GLDataFactory::destroyAllData()
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
for (IGraphicsData* data : m_committedData) for (IGraphicsData* data : m_committedData)
delete static_cast<GLData*>(data); delete static_cast<GLData*>(data);
for (IGraphicsBufferPool* pool : m_committedPools)
delete static_cast<GLPool*>(pool);
m_committedData.clear(); m_committedData.clear();
m_committedPools.clear();
}
void GLDataFactory::destroyPool(IGraphicsBufferPool* p)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
GLPool* pool = static_cast<GLPool*>(p);
m_committedPools.erase(pool);
delete pool;
}
IGraphicsBufferD* GLDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
size_t stride, size_t count)
{
GLPool* pool = static_cast<GLPool*>(p);
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count);
pool->m_DBufs.emplace_back(retval);
return retval;
} }
static const GLint SEMANTIC_COUNT_TABLE[] = static const GLint SEMANTIC_COUNT_TABLE[] =
@ -844,8 +880,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
for (int b=0 ; b<3 ; ++b) for (int b=0 ; b<3 ; ++b)
{ {
size_t offset = 0; size_t offset = fmt->m_baseVert * stride;
size_t instOffset = 0; size_t instOffset = fmt->m_baseInst * instStride;
glBindVertexArray(fmt->m_vao[b]); glBindVertexArray(fmt->m_vao[b]);
IGraphicsBuffer* lastVBO = nullptr; IGraphicsBuffer* lastVBO = nullptr;
IGraphicsBuffer* lastEBO = nullptr; IGraphicsBuffer* lastEBO = nullptr;
@ -1259,6 +1295,11 @@ struct GLCommandQueue : IGraphicsCommandQueue
for (std::unique_ptr<GLTextureD>& t : d->m_DTexs) for (std::unique_ptr<GLTextureD>& t : d->m_DTexs)
t->update(m_completeBuf); t->update(m_completeBuf);
} }
for (GLPool* p : gfxF->m_committedPools)
{
for (std::unique_ptr<GLGraphicsBufferD>& b : p->m_DBufs)
b->update(m_completeBuf);
}
datalk.unlock(); datalk.unlock();
glFlush(); glFlush();
@ -1464,10 +1505,12 @@ GLDataFactory::Context::newRenderTexture(size_t width, size_t height,
} }
GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount, GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements) const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
: m_q(q), : 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)
{ {
for (size_t i=0 ; i<elementCount ; ++i) for (size_t i=0 ; i<elementCount ; ++i)
m_elements[i] = elements[i]; m_elements[i] = elements[i];
@ -1476,10 +1519,11 @@ GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount,
GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);} GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);}
IVertexFormat* GLDataFactory::Context::newVertexFormat IVertexFormat* GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements) (size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
{ {
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent.m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent.m_parent->getCommandQueue());
GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements); GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements, baseVert, baseInst);
m_deferredData->m_VFmts.emplace_back(retval); m_deferredData->m_VFmts.emplace_back(retval);
return retval; return retval;
} }

View File

@ -31,6 +31,11 @@ struct MetalData : IGraphicsData
std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts; std::vector<std::unique_ptr<struct MetalVertexFormat>> m_VFmts;
}; };
struct MetalPool : IGraphicsBufferPool
{
std::vector<std::unique_ptr<class MetalGraphicsBufferD>> m_DBufs;
};
#define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_STATIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
#define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared #define MTL_DYNAMIC MTLResourceCPUCacheModeWriteCombined|MTLResourceStorageModeShared
@ -401,29 +406,29 @@ struct MetalVertexFormat : IVertexFormat
{ {
size_t m_elementCount; size_t m_elementCount;
MTLVertexDescriptor* m_vdesc; MTLVertexDescriptor* m_vdesc;
size_t m_stride = 0;
size_t m_instStride = 0;
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
: m_elementCount(elementCount) : m_elementCount(elementCount)
{ {
size_t stride = 0;
size_t instStride = 0;
for (size_t i=0 ; i<elementCount ; ++i) for (size_t i=0 ; i<elementCount ; ++i)
{ {
const VertexElementDescriptor* elemin = &elements[i]; const VertexElementDescriptor* elemin = &elements[i];
int semantic = int(elemin->semantic & VertexSemantic::SemanticMask); int semantic = int(elemin->semantic & VertexSemantic::SemanticMask);
if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None) if ((elemin->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
instStride += SEMANTIC_SIZE_TABLE[semantic]; m_instStride += SEMANTIC_SIZE_TABLE[semantic];
else else
stride += SEMANTIC_SIZE_TABLE[semantic]; m_stride += SEMANTIC_SIZE_TABLE[semantic];
} }
m_vdesc = [MTLVertexDescriptor vertexDescriptor]; m_vdesc = [MTLVertexDescriptor vertexDescriptor];
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.layouts[0]; MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.layouts[0];
layoutDesc.stride = stride; layoutDesc.stride = m_stride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex; layoutDesc.stepFunction = MTLVertexStepFunctionPerVertex;
layoutDesc.stepRate = 1; layoutDesc.stepRate = 1;
layoutDesc = m_vdesc.layouts[1]; layoutDesc = m_vdesc.layouts[1];
layoutDesc.stride = instStride; layoutDesc.stride = m_instStride;
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance; layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
layoutDesc.stepRate = 1; layoutDesc.stepRate = 1;
@ -475,14 +480,16 @@ class MetalShaderPipeline : public IShaderPipeline
{ {
friend class MetalDataFactory; friend class MetalDataFactory;
friend class MetalCommandQueue; friend class MetalCommandQueue;
friend struct MetalShaderDataBinding;
MTLCullMode m_cullMode = MTLCullModeNone; MTLCullMode m_cullMode = MTLCullModeNone;
MTLPrimitiveType m_drawPrim; MTLPrimitiveType m_drawPrim;
const MetalVertexFormat* m_vtxFmt;
MetalShaderPipeline(MetalContext* ctx, id<MTLFunction> vert, id<MTLFunction> frag, MetalShaderPipeline(MetalContext* ctx, id<MTLFunction> vert, id<MTLFunction> 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, bool backfaceCulling) bool depthTest, bool depthWrite, bool backfaceCulling)
: m_drawPrim(PRIMITIVE_TABLE[int(prim)]) : m_drawPrim(PRIMITIVE_TABLE[int(prim)]), m_vtxFmt(vtxFmt)
{ {
if (backfaceCulling) if (backfaceCulling)
m_cullMode = MTLCullModeBack; m_cullMode = MTLCullModeBack;
@ -580,12 +587,15 @@ struct MetalShaderDataBinding : IShaderDataBinding
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; std::unique_ptr<ITexture*[]> m_texs;
size_t m_baseVert;
size_t m_baseInst;
MetalShaderDataBinding(MetalContext* ctx, MetalShaderDataBinding(MetalContext* ctx,
IShaderPipeline* pipeline, 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 texCount, ITexture** texs, size_t baseVert, size_t baseInst)
: m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)), : m_pipeline(static_cast<MetalShaderPipeline*>(pipeline)),
m_vbuf(vbuf), m_vbuf(vbuf),
m_instVbo(instVbo), m_instVbo(instVbo),
@ -593,7 +603,9 @@ struct MetalShaderDataBinding : IShaderDataBinding
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 ITexture*[texCount]),
m_baseVert(baseVert),
m_baseInst(baseInst)
{ {
if (ubufCount && ubufStages) if (ubufCount && ubufStages)
{ {
@ -631,10 +643,13 @@ struct MetalShaderDataBinding : IShaderDataBinding
void bind(id<MTLRenderCommandEncoder> enc, int b) void bind(id<MTLRenderCommandEncoder> enc, int b)
{ {
m_pipeline->bind(enc); m_pipeline->bind(enc);
if (m_vbuf) if (m_vbuf)
[enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b) offset:0 atIndex:0]; [enc setVertexBuffer:GetBufferGPUResource(m_vbuf, b)
offset:m_pipeline->m_vtxFmt->m_stride * m_baseVert atIndex:0];
if (m_instVbo) if (m_instVbo)
[enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b) offset:0 atIndex:1]; [enc setVertexBuffer:GetBufferGPUResource(m_instVbo, b)
offset:m_pipeline->m_vtxFmt->m_instStride * 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)
{ {
@ -871,6 +886,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
for (std::unique_ptr<MetalTextureD>& t : d->m_DTexs) for (std::unique_ptr<MetalTextureD>& t : d->m_DTexs)
t->update(m_fillBuf); t->update(m_fillBuf);
} }
for (MetalPool* p : gfxF->m_committedPools)
{
for (std::unique_ptr<MetalGraphicsBufferD>& b : p->m_DBufs)
b->update(m_fillBuf);
}
datalk.unlock(); datalk.unlock();
@autoreleasepool @autoreleasepool
@ -1048,7 +1068,8 @@ ITextureR* MetalDataFactory::Context::newRenderTexture(size_t width, size_t heig
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)
{ {
MetalVertexFormat* retval = new struct MetalVertexFormat(elementCount, elements); MetalVertexFormat* retval = new struct MetalVertexFormat(elementCount, elements);
m_deferredData->m_VFmts.emplace_back(retval); m_deferredData->m_VFmts.emplace_back(retval);
@ -1091,11 +1112,12 @@ 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 texCount, ITexture** texs, size_t baseVert, size_t baseInst)
{ {
MetalShaderDataBinding* retval = MetalShaderDataBinding* retval =
new MetalShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf, new MetalShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbo, ibuf,
ubufCount, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs); ubufCount, ubufs, ubufStages, ubufOffs,
ubufSizes, texCount, texs, baseVert, baseInst);
m_deferredData->m_SBinds.emplace_back(retval); m_deferredData->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -1120,6 +1142,15 @@ GraphicsDataToken MetalDataFactory::commitTransaction(const FactoryCommitFunc& t
m_committedData.insert(retval); m_committedData.insert(retval);
return GraphicsDataToken(this, retval); return GraphicsDataToken(this, retval);
} }
GraphicsBufferPoolToken MetalDataFactory::newBufferPool()
{
std::unique_lock<std::mutex> lk(m_committedMutex);
MetalPool* retval = new MetalPool;
m_committedPools.insert(retval);
return GraphicsBufferPoolToken(this, retval);
}
void MetalDataFactory::destroyData(IGraphicsData* d) void MetalDataFactory::destroyData(IGraphicsData* d)
{ {
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
@ -1127,12 +1158,34 @@ void MetalDataFactory::destroyData(IGraphicsData* d)
m_committedData.erase(data); m_committedData.erase(data);
delete data; delete data;
} }
void MetalDataFactory::destroyAllData() void MetalDataFactory::destroyAllData()
{ {
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
for (IGraphicsData* data : m_committedData) for (IGraphicsData* data : m_committedData)
delete static_cast<MetalData*>(data); delete static_cast<MetalData*>(data);
for (IGraphicsBufferPool* pool : m_committedPools)
delete static_cast<MetalPool*>(pool);
m_committedData.clear(); m_committedData.clear();
m_committedPools.clear();
}
void MetalDataFactory::destroyPool(IGraphicsBufferPool* p)
{
std::unique_lock<std::mutex> lk(m_committedMutex);
MetalPool* pool = static_cast<MetalPool*>(p);
m_committedPools.erase(pool);
delete pool;
}
IGraphicsBufferD* MetalDataFactory::newPoolBuffer(IGraphicsBufferPool* p, BufferUse use,
size_t stride, size_t count)
{
MetalPool* pool = static_cast<MetalPool*>(p);
MetalCommandQueue* q = static_cast<MetalCommandQueue*>(m_parent->getCommandQueue());
MetalGraphicsBufferD* retval = new MetalGraphicsBufferD(q, use, m_ctx, stride, count);
pool->m_DBufs.emplace_back(retval);
return retval;
} }
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,

View File

@ -1123,8 +1123,9 @@ static boo::ESpecialKey translateKeycode(short code)
- (void)reshape - (void)reshape
{ {
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y), NSRect frame = [self convertRectToBacking:self.frame];
int(self.frame.size.width), int(self.frame.size.height)}; boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y),
int(frame.size.width), int(frame.size.height)};
if (resp->booContext->m_callback) if (resp->booContext->m_callback)
resp->booContext->m_callback->resized(rect); resp->booContext->m_callback->resized(rect);
[super reshape]; [super reshape];
@ -1145,6 +1146,11 @@ static boo::ESpecialKey translateKeycode(short code)
return resp; return resp;
} }
- (BOOL)wantsBestResolutionOpenGLSurface
{
return YES;
}
@end @end
#if BOO_HAS_METAL #if BOO_HAS_METAL
@ -1193,8 +1199,9 @@ static boo::ESpecialKey translateKeycode(short code)
- (void)reshapeHandler - (void)reshapeHandler
{ {
boo::SWindowRect rect = {int(self.frame.origin.x), int(self.frame.origin.y), NSRect frame = [self convertRectToBacking:self.frame];
int(self.frame.size.width), int(self.frame.size.height)}; boo::SWindowRect rect = {int(frame.origin.x), int(frame.origin.y),
int(frame.size.width), int(frame.size.height)};
boo::MetalContext::Window& w = m_ctx->m_windows[m_window]; boo::MetalContext::Window& w = m_ctx->m_windows[m_window];
std::unique_lock<std::mutex> lk(w.m_resizeLock); std::unique_lock<std::mutex> lk(w.m_resizeLock);
if (resp->booContext->m_callback) if (resp->booContext->m_callback)
@ -1351,7 +1358,8 @@ public:
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{ {
NSRect wFrame = [[m_nsWindow contentView] frame]; NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x; xOut = wFrame.origin.x;
yOut = wFrame.origin.y; yOut = wFrame.origin.y;
wOut = wFrame.size.width; wOut = wFrame.size.width;
@ -1360,7 +1368,8 @@ public:
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{ {
NSRect wFrame = [[m_nsWindow contentView] frame]; NSView* view = [m_nsWindow contentView];
NSRect wFrame = [view convertRectToBacking:view.frame];
xOut = wFrame.origin.x; xOut = wFrame.origin.x;
yOut = wFrame.origin.y; yOut = wFrame.origin.y;
wOut = wFrame.size.width; wOut = wFrame.size.width;
@ -1525,7 +1534,8 @@ IWindow* _WindowCocoaNew(const SystemString& title, NSOpenGLContext* lastGLCtx,
styleMask:NSWindowStyleMaskTitled| styleMask:NSWindowStyleMaskTitled|
NSWindowStyleMaskClosable| NSWindowStyleMaskClosable|
NSWindowStyleMaskMiniaturizable| NSWindowStyleMaskMiniaturizable|
NSWindowStyleMaskTitled NSWindowStyleMaskTitled|
NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
defer:YES]; defer:YES];
self.releasedWhenClosed = NO; self.releasedWhenClosed = NO;