Brought metal in sync

This commit is contained in:
Jack Andersen 2015-12-02 12:25:30 -10:00
parent d0bdb40f0e
commit fc4234708f
2 changed files with 85 additions and 27 deletions

View File

@ -20,9 +20,10 @@ struct MetalContext;
class MetalDataFactory : public IGraphicsDataFactory
{
friend struct MetalCommandQueue;
IGraphicsContext* m_parent;
IGraphicsData* m_deferredData = nullptr;
std::unordered_set<IGraphicsData*> m_committedData;
struct MetalData* m_deferredData = nullptr;
std::unordered_set<struct MetalData*> m_committedData;
struct MetalContext* m_ctx;
public:
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);

View File

@ -51,12 +51,16 @@ class MetalGraphicsBufferD : public IGraphicsBufferD
friend class MetalDataFactory;
friend struct MetalCommandQueue;
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)
{
m_cpuBuf.reset(new uint8_t[m_sz]);
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];
}
void update(int b);
public:
size_t m_stride;
size_t m_count;
@ -65,8 +69,6 @@ public:
MetalGraphicsBufferD() = default;
void load(const void* data, size_t sz);
size_t m_mappedSz;
void* map(size_t sz);
void unmap();
};
@ -167,14 +169,35 @@ class MetalTextureD : public ITextureD
MetalCommandQueue* m_q;
size_t m_width = 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)
: 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;
@autoreleasepool
{
desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
desc = [[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
width:width height:height
mipmapped:NO] retain];
}
@ -182,6 +205,7 @@ class MetalTextureD : public ITextureD
m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
}
void update(int b);
public:
NSPtr<id<MTLTexture>> m_texs[2];
~MetalTextureD() = default;
@ -567,8 +591,6 @@ struct MetalCommandQueue : IGraphicsCommandQueue
[m_enc.get() setScissorRect:scissor];
}
int pendingDynamicSlot() {return m_fillBuf;}
std::unordered_map<MetalTextureR*, std::pair<size_t, size_t>> m_texResizes;
void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)
{
@ -664,6 +686,20 @@ struct MetalCommandQueue : IGraphicsCommandQueue
bool m_inProgress = false;
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
{
/* Abandon if in progress (renderer too slow) */
@ -684,9 +720,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
}
m_drawBuf = m_fillBuf;
++m_fillBuf;
if (m_fillBuf == 2)
m_fillBuf = 0;
m_fillBuf ^= 1;
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
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)
{
id<MTLBuffer> res = m_bufs[m_q->m_fillBuf].get();
memcpy(res.contents, data, sz);
size_t bufSz = std::min(sz, m_sz);
memcpy(m_cpuBuf.get(), data, bufSz);
m_validSlots = 0;
}
void* MetalGraphicsBufferD::map(size_t sz)
{
m_mappedSz = sz;
id<MTLBuffer> res = m_bufs[m_q->m_fillBuf].get();
return res.contents;
if (sz > m_sz)
return nullptr;
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)
{
id<MTLTexture> res = m_texs[m_q->m_fillBuf].get();
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
mipmapLevel:0 withBytes:data bytesPerRow:m_width*4];
size_t bufSz = std::min(sz, m_cpuSz);
memcpy(m_cpuBuf.get(), data, bufSz);
m_validSlots = 0;
}
void* MetalTextureD::map(size_t sz)
{
m_mappedBuf = malloc(sz);
return m_mappedBuf;
if (sz > m_cpuSz)
return nullptr;
return m_cpuBuf.get();
}
void MetalTextureD::unmap()
{
id<MTLTexture> res = m_texs[m_q->m_fillBuf].get();
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
mipmapLevel:0 withBytes:m_mappedBuf bytesPerRow:m_width*4];
free(m_mappedBuf);
m_validSlots = 0;
}
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)