mirror of https://github.com/AxioDL/boo.git
Brought metal in sync
This commit is contained in:
parent
d0bdb40f0e
commit
fc4234708f
|
@ -20,9 +20,10 @@ struct MetalContext;
|
||||||
|
|
||||||
class MetalDataFactory : public IGraphicsDataFactory
|
class MetalDataFactory : public IGraphicsDataFactory
|
||||||
{
|
{
|
||||||
|
friend struct MetalCommandQueue;
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
IGraphicsData* m_deferredData = nullptr;
|
struct MetalData* m_deferredData = nullptr;
|
||||||
std::unordered_set<IGraphicsData*> m_committedData;
|
std::unordered_set<struct MetalData*> m_committedData;
|
||||||
struct MetalContext* m_ctx;
|
struct MetalContext* m_ctx;
|
||||||
public:
|
public:
|
||||||
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
||||||
|
|
|
@ -51,12 +51,16 @@ class MetalGraphicsBufferD : public IGraphicsBufferD
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
MetalCommandQueue* m_q;
|
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)
|
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)
|
: 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.get() newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
m_bufs[0] = [ctx->m_dev.get() newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
||||||
m_bufs[1] = [ctx->m_dev.get() newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
m_bufs[1] = [ctx->m_dev.get() newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
||||||
}
|
}
|
||||||
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
size_t m_stride;
|
size_t m_stride;
|
||||||
size_t m_count;
|
size_t m_count;
|
||||||
|
@ -65,8 +69,6 @@ public:
|
||||||
MetalGraphicsBufferD() = default;
|
MetalGraphicsBufferD() = default;
|
||||||
|
|
||||||
void load(const void* data, size_t sz);
|
void load(const void* data, size_t sz);
|
||||||
|
|
||||||
size_t m_mappedSz;
|
|
||||||
void* map(size_t sz);
|
void* map(size_t sz);
|
||||||
void unmap();
|
void unmap();
|
||||||
};
|
};
|
||||||
|
@ -167,14 +169,35 @@ class MetalTextureD : public ITextureD
|
||||||
MetalCommandQueue* m_q;
|
MetalCommandQueue* m_q;
|
||||||
size_t m_width = 0;
|
size_t m_width = 0;
|
||||||
size_t m_height = 0;
|
size_t m_height = 0;
|
||||||
void* m_mappedBuf;
|
std::unique_ptr<uint8_t[]> m_cpuBuf;
|
||||||
|
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)
|
MetalTextureD(MetalCommandQueue* q, MetalContext* ctx, size_t width, size_t height, TextureFormat fmt)
|
||||||
: m_q(q), m_width(width), m_height(height)
|
: m_q(q), m_width(width), m_height(height)
|
||||||
{
|
{
|
||||||
|
MTLPixelFormat format;
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
case TextureFormat::RGBA8:
|
||||||
|
format = MTLPixelFormatRGBA8Unorm;
|
||||||
|
m_pxPitch = 4;
|
||||||
|
break;
|
||||||
|
case TextureFormat::I8:
|
||||||
|
format = MTLPixelFormatR8Unorm;
|
||||||
|
m_pxPitch = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.report(LogVisor::FatalError, "unsupported tex format");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cpuSz = width * height * m_pxPitch;
|
||||||
|
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
NSPtr<MTLTextureDescriptor*> desc;
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
|
desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||||
width:width height:height
|
width:width height:height
|
||||||
mipmapped:NO] retain];
|
mipmapped:NO] retain];
|
||||||
}
|
}
|
||||||
|
@ -182,6 +205,7 @@ class MetalTextureD : public ITextureD
|
||||||
m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
||||||
m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
||||||
}
|
}
|
||||||
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_texs[2];
|
NSPtr<id<MTLTexture>> m_texs[2];
|
||||||
~MetalTextureD() = default;
|
~MetalTextureD() = default;
|
||||||
|
@ -566,9 +590,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
NSUInteger(rect.size[0]), NSUInteger(rect.size[1])};
|
NSUInteger(rect.size[0]), NSUInteger(rect.size[1])};
|
||||||
[m_enc.get() setScissorRect:scissor];
|
[m_enc.get() setScissorRect:scissor];
|
||||||
}
|
}
|
||||||
|
|
||||||
int pendingDynamicSlot() {return m_fillBuf;}
|
|
||||||
|
|
||||||
std::unordered_map<MetalTextureR*, std::pair<size_t, size_t>> m_texResizes;
|
std::unordered_map<MetalTextureR*, std::pair<size_t, size_t>> m_texResizes;
|
||||||
void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)
|
void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)
|
||||||
{
|
{
|
||||||
|
@ -664,6 +686,20 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
bool m_inProgress = false;
|
bool m_inProgress = false;
|
||||||
void execute()
|
void execute()
|
||||||
{
|
{
|
||||||
|
/* Update dynamic data here */
|
||||||
|
MetalDataFactory* gfxF = static_cast<MetalDataFactory*>(m_parent->getDataFactory());
|
||||||
|
for (MetalData* d : gfxF->m_committedData)
|
||||||
|
{
|
||||||
|
for (std::unique_ptr<MetalGraphicsBufferD>& b : d->m_DBufs)
|
||||||
|
b->update(m_fillBuf);
|
||||||
|
for (std::unique_ptr<MetalTextureD>& t : d->m_DTexs)
|
||||||
|
t->update(m_fillBuf);
|
||||||
|
}
|
||||||
|
for (std::unique_ptr<MetalGraphicsBufferD>& b : gfxF->m_deferredData->m_DBufs)
|
||||||
|
b->update(m_fillBuf);
|
||||||
|
for (std::unique_ptr<MetalTextureD>& t : gfxF->m_deferredData->m_DTexs)
|
||||||
|
t->update(m_fillBuf);
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
/* Abandon if in progress (renderer too slow) */
|
/* Abandon if in progress (renderer too slow) */
|
||||||
|
@ -684,9 +720,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
m_drawBuf = m_fillBuf;
|
m_drawBuf = m_fillBuf;
|
||||||
++m_fillBuf;
|
m_fillBuf ^= 1;
|
||||||
if (m_fillBuf == 2)
|
|
||||||
m_fillBuf = 0;
|
|
||||||
|
|
||||||
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
||||||
m_inProgress = true;
|
m_inProgress = true;
|
||||||
|
@ -696,36 +730,59 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void MetalGraphicsBufferD::update(int b)
|
||||||
|
{
|
||||||
|
int slot = 1 << b;
|
||||||
|
if ((slot & m_validSlots) == 0)
|
||||||
|
{
|
||||||
|
id<MTLBuffer> res = m_bufs[b].get();
|
||||||
|
memcpy(res.contents, m_cpuBuf.get(), m_sz);
|
||||||
|
m_validSlots |= slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
void MetalGraphicsBufferD::load(const void* data, size_t sz)
|
void MetalGraphicsBufferD::load(const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
id<MTLBuffer> res = m_bufs[m_q->m_fillBuf].get();
|
size_t bufSz = std::min(sz, m_sz);
|
||||||
memcpy(res.contents, data, sz);
|
memcpy(m_cpuBuf.get(), data, bufSz);
|
||||||
|
m_validSlots = 0;
|
||||||
}
|
}
|
||||||
void* MetalGraphicsBufferD::map(size_t sz)
|
void* MetalGraphicsBufferD::map(size_t sz)
|
||||||
{
|
{
|
||||||
m_mappedSz = sz;
|
if (sz > m_sz)
|
||||||
id<MTLBuffer> res = m_bufs[m_q->m_fillBuf].get();
|
return nullptr;
|
||||||
return res.contents;
|
return m_cpuBuf.get();
|
||||||
|
}
|
||||||
|
void MetalGraphicsBufferD::unmap()
|
||||||
|
{
|
||||||
|
m_validSlots = 0;
|
||||||
}
|
}
|
||||||
void MetalGraphicsBufferD::unmap() {}
|
|
||||||
|
|
||||||
|
void MetalTextureD::update(int b)
|
||||||
|
{
|
||||||
|
int slot = 1 << b;
|
||||||
|
if ((slot & m_validSlots) == 0)
|
||||||
|
{
|
||||||
|
id<MTLTexture> res = m_texs[b].get();
|
||||||
|
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
||||||
|
mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch];
|
||||||
|
m_validSlots |= slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
void MetalTextureD::load(const void* data, size_t sz)
|
void MetalTextureD::load(const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
id<MTLTexture> res = m_texs[m_q->m_fillBuf].get();
|
size_t bufSz = std::min(sz, m_cpuSz);
|
||||||
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
memcpy(m_cpuBuf.get(), data, bufSz);
|
||||||
mipmapLevel:0 withBytes:data bytesPerRow:m_width*4];
|
m_validSlots = 0;
|
||||||
}
|
}
|
||||||
void* MetalTextureD::map(size_t sz)
|
void* MetalTextureD::map(size_t sz)
|
||||||
{
|
{
|
||||||
m_mappedBuf = malloc(sz);
|
if (sz > m_cpuSz)
|
||||||
return m_mappedBuf;
|
return nullptr;
|
||||||
|
return m_cpuBuf.get();
|
||||||
}
|
}
|
||||||
void MetalTextureD::unmap()
|
void MetalTextureD::unmap()
|
||||||
{
|
{
|
||||||
id<MTLTexture> res = m_texs[m_q->m_fillBuf].get();
|
m_validSlots = 0;
|
||||||
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
|
||||||
mipmapLevel:0 withBytes:m_mappedBuf bytesPerRow:m_width*4];
|
|
||||||
free(m_mappedBuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
|
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
|
||||||
|
|
Loading…
Reference in New Issue