mirror of https://github.com/AxioDL/boo.git
better OpenGL mipmap configuration
This commit is contained in:
parent
e9bd443e49
commit
77e9492b43
|
@ -267,12 +267,16 @@ class GraphicsDataToken
|
||||||
IGraphicsData* m_data = nullptr;
|
IGraphicsData* m_data = nullptr;
|
||||||
GraphicsDataToken(IGraphicsDataFactory* factory, IGraphicsData* data)
|
GraphicsDataToken(IGraphicsDataFactory* factory, IGraphicsData* data)
|
||||||
: m_factory(factory), m_data(data) {}
|
: m_factory(factory), m_data(data) {}
|
||||||
|
public:
|
||||||
void doDestroy()
|
void doDestroy()
|
||||||
{
|
{
|
||||||
if (m_factory && m_data)
|
if (m_factory && m_data)
|
||||||
|
{
|
||||||
m_factory->destroyData(m_data);
|
m_factory->destroyData(m_data);
|
||||||
|
m_factory = nullptr;
|
||||||
|
m_data = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
GraphicsDataToken() = default;
|
GraphicsDataToken() = default;
|
||||||
GraphicsDataToken(const GraphicsDataToken& other) = delete;
|
GraphicsDataToken(const GraphicsDataToken& other) = delete;
|
||||||
GraphicsDataToken(GraphicsDataToken&& other)
|
GraphicsDataToken(GraphicsDataToken&& other)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
struct MetalContext;
|
struct MetalContext;
|
||||||
|
|
||||||
class MetalDataFactory : public IGraphicsDataFactory
|
class MetalDataFactory : public IGraphicsDataFactory
|
||||||
{
|
{
|
||||||
friend struct MetalCommandQueue;
|
friend struct MetalCommandQueue;
|
||||||
|
@ -27,44 +27,45 @@ class MetalDataFactory : public IGraphicsDataFactory
|
||||||
std::unordered_set<struct MetalData*> m_committedData;
|
std::unordered_set<struct MetalData*> m_committedData;
|
||||||
std::mutex m_committedMutex;
|
std::mutex m_committedMutex;
|
||||||
struct MetalContext* m_ctx;
|
struct MetalContext* m_ctx;
|
||||||
|
|
||||||
void destroyData(IGraphicsData*);
|
void destroyData(IGraphicsData*);
|
||||||
void destroyAllData();
|
void destroyAllData();
|
||||||
public:
|
public:
|
||||||
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
||||||
~MetalDataFactory() {}
|
~MetalDataFactory() {}
|
||||||
|
|
||||||
Platform platform() const {return Platform::Metal;}
|
Platform platform() const {return Platform::Metal;}
|
||||||
const char* platformName() const {return "Metal";}
|
const char* platformName() const {return "Metal";}
|
||||||
|
|
||||||
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
|
||||||
IGraphicsBufferS* newStaticBuffer(BufferUse use, std::unique_ptr<uint8_t[]>&& data, size_t stride, size_t count);
|
IGraphicsBufferS* newStaticBuffer(BufferUse use, std::unique_ptr<uint8_t[]>&& data, size_t stride, size_t count);
|
||||||
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
|
||||||
|
|
||||||
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
const void* data, size_t sz);
|
const void* data, size_t sz);
|
||||||
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
GraphicsDataToken
|
||||||
std::unique_ptr<uint8_t[]>&& data, size_t sz);
|
newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
|
const void* data, size_t sz, ITextureS** texOut);
|
||||||
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
|
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
|
||||||
const void* data, size_t sz);
|
const void* data, size_t sz);
|
||||||
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
|
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
|
||||||
ITextureR* newRenderTexture(size_t width, size_t height, size_t samples);
|
ITextureR* newRenderTexture(size_t width, size_t height, size_t samples);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||||
IVertexFormat* vtxFmt, unsigned targetSamples,
|
IVertexFormat* vtxFmt, unsigned targetSamples,
|
||||||
BlendFactor srcFac, BlendFactor dstFac,
|
BlendFactor srcFac, BlendFactor dstFac,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling);
|
bool depthTest, bool depthWrite, bool backfaceCulling);
|
||||||
|
|
||||||
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,
|
size_t ubufCount, IGraphicsBuffer** ubufs,
|
||||||
size_t texCount, ITexture** texs);
|
size_t texCount, ITexture** texs);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
GraphicsDataToken commit();
|
GraphicsDataToken commit();
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,7 +127,10 @@ class GLTextureS : public ITextureS
|
||||||
glBindTexture(GL_TEXTURE_2D, m_tex);
|
glBindTexture(GL_TEXTURE_2D, m_tex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
if (mips > 1)
|
if (mips > 1)
|
||||||
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mips-1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
@ -147,7 +150,7 @@ class GLTextureS : public ITextureS
|
||||||
pxPitch = 1;
|
pxPitch = 1;
|
||||||
break;
|
break;
|
||||||
case TextureFormat::DXT1:
|
case TextureFormat::DXT1:
|
||||||
intFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
intFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
compressed = true;
|
compressed = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -255,12 +258,12 @@ public:
|
||||||
glActiveTexture(GL_TEXTURE0 + idx);
|
glActiveTexture(GL_TEXTURE0 + idx);
|
||||||
glBindTexture(m_target, m_texs[0]);
|
glBindTexture(m_target, m_texs[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(size_t width, size_t height)
|
void resize(size_t width, size_t height)
|
||||||
{
|
{
|
||||||
m_width = width;
|
m_width = width;
|
||||||
m_height = height;
|
m_height = height;
|
||||||
|
|
||||||
if (m_samples > 1)
|
if (m_samples > 1)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]);
|
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]);
|
||||||
|
@ -1115,7 +1118,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
|
||||||
cmds.emplace_back(Command::Op::Present);
|
cmds.emplace_back(Command::Op::Present);
|
||||||
cmds.back().source = source;
|
cmds.back().source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addVertexFormat(GLVertexFormat* fmt)
|
void addVertexFormat(GLVertexFormat* fmt)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_mt);
|
std::unique_lock<std::mutex> lk(m_mt);
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
size_t m_sz;
|
size_t m_sz;
|
||||||
id<MTLBuffer> m_bufs[2];
|
id<MTLBuffer> m_bufs[2];
|
||||||
MetalGraphicsBufferD() = default;
|
MetalGraphicsBufferD() = default;
|
||||||
|
|
||||||
void load(const void* data, size_t sz);
|
void load(const void* data, size_t sz);
|
||||||
void* map(size_t sz);
|
void* map(size_t sz);
|
||||||
void unmap();
|
void unmap();
|
||||||
|
@ -85,16 +85,21 @@ class MetalTextureS : public ITextureS
|
||||||
TextureFormat fmt, const void* data, size_t sz)
|
TextureFormat fmt, const void* data, size_t sz)
|
||||||
{
|
{
|
||||||
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
MTLPixelFormat pfmt = MTLPixelFormatRGBA8Unorm;
|
||||||
NSUInteger ppitch = 4;
|
NSUInteger ppitchNum = 4;
|
||||||
|
NSUInteger ppitchDenom = 1;
|
||||||
switch (fmt)
|
switch (fmt)
|
||||||
{
|
{
|
||||||
case TextureFormat::I8:
|
case TextureFormat::I8:
|
||||||
pfmt = MTLPixelFormatR8Unorm;
|
pfmt = MTLPixelFormatR8Unorm;
|
||||||
ppitch = 1;
|
ppitchNum = 1;
|
||||||
break;
|
break;
|
||||||
|
case TextureFormat::DXT1:
|
||||||
|
pfmt = MTLPixelFormatBC1_RGBA;
|
||||||
|
ppitchNum = 1;
|
||||||
|
ppitchDenom = 2;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
MTLTextureDescriptor* desc =
|
MTLTextureDescriptor* desc =
|
||||||
|
@ -110,8 +115,8 @@ class MetalTextureS : public ITextureS
|
||||||
[m_tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
[m_tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||||
mipmapLevel:i
|
mipmapLevel:i
|
||||||
withBytes:dataIt
|
withBytes:dataIt
|
||||||
bytesPerRow:width * ppitch];
|
bytesPerRow:width * ppitchNum / ppitchDenom];
|
||||||
dataIt += width * height * ppitch;
|
dataIt += width * height * ppitchNum / ppitchDenom;
|
||||||
width /= 2;
|
width /= 2;
|
||||||
height /= 2;
|
height /= 2;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +126,7 @@ public:
|
||||||
id<MTLTexture> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureS() = default;
|
~MetalTextureS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureSA : public ITextureSA
|
class MetalTextureSA : public ITextureSA
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
|
@ -138,7 +143,7 @@ class MetalTextureSA : public ITextureSA
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
MTLTextureDescriptor* desc =
|
MTLTextureDescriptor* desc =
|
||||||
|
@ -166,7 +171,7 @@ public:
|
||||||
id<MTLTexture> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureSA() = default;
|
~MetalTextureSA() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureD : public ITextureD
|
class MetalTextureD : public ITextureD
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
|
@ -195,10 +200,10 @@ class MetalTextureD : public ITextureD
|
||||||
default:
|
default:
|
||||||
Log.report(LogVisor::FatalError, "unsupported tex format");
|
Log.report(LogVisor::FatalError, "unsupported tex format");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cpuSz = width * height * m_pxPitch;
|
m_cpuSz = width * height * m_pxPitch;
|
||||||
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
|
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
MTLTextureDescriptor* desc =
|
MTLTextureDescriptor* desc =
|
||||||
|
@ -214,12 +219,12 @@ class MetalTextureD : public ITextureD
|
||||||
public:
|
public:
|
||||||
id<MTLTexture> m_texs[2];
|
id<MTLTexture> m_texs[2];
|
||||||
~MetalTextureD() = default;
|
~MetalTextureD() = default;
|
||||||
|
|
||||||
void load(const void* data, size_t sz);
|
void load(const void* data, size_t sz);
|
||||||
void* map(size_t sz);
|
void* map(size_t sz);
|
||||||
void unmap();
|
void unmap();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalTextureR : public ITextureR
|
class MetalTextureR : public ITextureR
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
|
@ -227,7 +232,7 @@ class MetalTextureR : public ITextureR
|
||||||
size_t m_width = 0;
|
size_t m_width = 0;
|
||||||
size_t m_height = 0;
|
size_t m_height = 0;
|
||||||
size_t m_samples = 0;
|
size_t m_samples = 0;
|
||||||
|
|
||||||
void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples)
|
void Setup(MetalContext* ctx, size_t width, size_t height, size_t samples)
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
|
@ -275,7 +280,7 @@ class MetalTextureR : public ITextureR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalTextureR(MetalContext* ctx, size_t width, size_t height, size_t samples)
|
MetalTextureR(MetalContext* ctx, size_t width, size_t height, size_t samples)
|
||||||
: m_width(width), m_height(height), m_samples(samples)
|
: m_width(width), m_height(height), m_samples(samples)
|
||||||
{
|
{
|
||||||
|
@ -289,7 +294,7 @@ public:
|
||||||
id<MTLTexture> m_depthTex;
|
id<MTLTexture> m_depthTex;
|
||||||
MTLRenderPassDescriptor* m_passDesc;
|
MTLRenderPassDescriptor* m_passDesc;
|
||||||
~MetalTextureR() = default;
|
~MetalTextureR() = default;
|
||||||
|
|
||||||
void resize(MetalContext* ctx, size_t width, size_t height)
|
void resize(MetalContext* ctx, size_t width, size_t height)
|
||||||
{
|
{
|
||||||
if (width < 1)
|
if (width < 1)
|
||||||
|
@ -300,10 +305,10 @@ public:
|
||||||
m_height = height;
|
m_height = height;
|
||||||
Setup(ctx, width, height, m_samples);
|
Setup(ctx, width, height, m_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> getRenderColorRes() {if (m_samples > 1) return m_msaaTex; return m_tex;}
|
id<MTLTexture> getRenderColorRes() {if (m_samples > 1) return m_msaaTex; return m_tex;}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const size_t SEMANTIC_SIZE_TABLE[] =
|
static const size_t SEMANTIC_SIZE_TABLE[] =
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
|
@ -352,18 +357,18 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
else
|
else
|
||||||
stride += SEMANTIC_SIZE_TABLE[semantic];
|
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 = 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 = instStride;
|
||||||
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
|
layoutDesc.stepFunction = MTLVertexStepFunctionPerInstance;
|
||||||
layoutDesc.stepRate = 1;
|
layoutDesc.stepRate = 1;
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t instOffset = 0;
|
size_t instOffset = 0;
|
||||||
for (size_t i=0 ; i<elementCount ; ++i)
|
for (size_t i=0 ; i<elementCount ; ++i)
|
||||||
|
@ -387,7 +392,7 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const MTLBlendFactor BLEND_FACTOR_TABLE[] =
|
static const MTLBlendFactor BLEND_FACTOR_TABLE[] =
|
||||||
{
|
{
|
||||||
MTLBlendFactorZero,
|
MTLBlendFactorZero,
|
||||||
|
@ -406,7 +411,7 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
{
|
{
|
||||||
friend class MetalDataFactory;
|
friend class MetalDataFactory;
|
||||||
MTLCullMode m_cullMode = MTLCullModeNone;
|
MTLCullMode m_cullMode = MTLCullModeNone;
|
||||||
|
|
||||||
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,
|
BlendFactor srcFac, BlendFactor dstFac,
|
||||||
|
@ -414,7 +419,7 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
{
|
{
|
||||||
if (backfaceCulling)
|
if (backfaceCulling)
|
||||||
m_cullMode = MTLCullModeBack;
|
m_cullMode = MTLCullModeBack;
|
||||||
|
|
||||||
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
||||||
desc.vertexFunction = vert;
|
desc.vertexFunction = vert;
|
||||||
desc.fragmentFunction = frag;
|
desc.fragmentFunction = frag;
|
||||||
|
@ -431,7 +436,7 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
if (err)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error making shader pipeline: %s",
|
Log.report(LogVisor::FatalError, "error making shader pipeline: %s",
|
||||||
[[err localizedDescription] UTF8String]);
|
[[err localizedDescription] UTF8String]);
|
||||||
|
|
||||||
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
|
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
|
||||||
if (depthTest)
|
if (depthTest)
|
||||||
dsDesc.depthCompareFunction = MTLCompareFunctionLessEqual;
|
dsDesc.depthCompareFunction = MTLCompareFunctionLessEqual;
|
||||||
|
@ -444,7 +449,7 @@ public:
|
||||||
~MetalShaderPipeline() = default;
|
~MetalShaderPipeline() = default;
|
||||||
MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete;
|
MetalShaderPipeline& operator=(const MetalShaderPipeline&) = delete;
|
||||||
MetalShaderPipeline(const MetalShaderPipeline&) = delete;
|
MetalShaderPipeline(const MetalShaderPipeline&) = delete;
|
||||||
|
|
||||||
void bind(id<MTLRenderCommandEncoder> enc)
|
void bind(id<MTLRenderCommandEncoder> enc)
|
||||||
{
|
{
|
||||||
[enc setRenderPipelineState:m_state];
|
[enc setRenderPipelineState:m_state];
|
||||||
|
@ -452,7 +457,7 @@ public:
|
||||||
[enc setCullMode:m_cullMode];
|
[enc setCullMode:m_cullMode];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
|
static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
|
||||||
{
|
{
|
||||||
if (buf->dynamic())
|
if (buf->dynamic())
|
||||||
|
@ -525,7 +530,7 @@ struct MetalShaderDataBinding : IShaderDataBinding
|
||||||
for (size_t i=0 ; i<texCount ; ++i)
|
for (size_t i=0 ; i<texCount ; ++i)
|
||||||
m_texs[i] = texs[i];
|
m_texs[i] = texs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(id<MTLRenderCommandEncoder> enc, int b)
|
void bind(id<MTLRenderCommandEncoder> enc, int b)
|
||||||
{
|
{
|
||||||
m_pipeline->bind(enc);
|
m_pipeline->bind(enc);
|
||||||
|
@ -550,10 +555,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
id<MTLCommandBuffer> m_cmdBuf;
|
id<MTLCommandBuffer> m_cmdBuf;
|
||||||
id<MTLRenderCommandEncoder> m_enc;
|
id<MTLRenderCommandEncoder> m_enc;
|
||||||
bool m_running = true;
|
bool m_running = true;
|
||||||
|
|
||||||
size_t m_fillBuf = 0;
|
size_t m_fillBuf = 0;
|
||||||
size_t m_drawBuf = 0;
|
size_t m_drawBuf = 0;
|
||||||
|
|
||||||
MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent)
|
MetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsContext* parent)
|
||||||
: m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent)
|
: m_ctx(ctx), m_parentWindow(parentWindow), m_parent(parent)
|
||||||
{
|
{
|
||||||
|
@ -562,19 +567,19 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
m_cmdBuf = [ctx->m_q commandBuffer];
|
m_cmdBuf = [ctx->m_q commandBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopRenderer()
|
void stopRenderer()
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
if (m_inProgress)
|
if (m_inProgress)
|
||||||
[m_cmdBuf waitUntilCompleted];
|
[m_cmdBuf waitUntilCompleted];
|
||||||
}
|
}
|
||||||
|
|
||||||
~MetalCommandQueue()
|
~MetalCommandQueue()
|
||||||
{
|
{
|
||||||
if (m_running) stopRenderer();
|
if (m_running) stopRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalShaderDataBinding* m_boundData = nullptr;
|
MetalShaderDataBinding* m_boundData = nullptr;
|
||||||
void setShaderDataBinding(IShaderDataBinding* binding)
|
void setShaderDataBinding(IShaderDataBinding* binding)
|
||||||
{
|
{
|
||||||
|
@ -582,7 +587,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
cbind->bind(m_enc, m_fillBuf);
|
cbind->bind(m_enc, m_fillBuf);
|
||||||
m_boundData = cbind;
|
m_boundData = cbind;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalTextureR* m_boundTarget = nullptr;
|
MetalTextureR* m_boundTarget = nullptr;
|
||||||
void setRenderTarget(ITextureR* target)
|
void setRenderTarget(ITextureR* target)
|
||||||
{
|
{
|
||||||
|
@ -594,14 +599,14 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
m_boundTarget = ctarget;
|
m_boundTarget = ctarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setViewport(const SWindowRect& rect)
|
void setViewport(const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
MTLViewport vp = {double(rect.location[0]), double(rect.location[1]),
|
MTLViewport vp = {double(rect.location[0]), double(rect.location[1]),
|
||||||
double(rect.size[0]), double(rect.size[1]), 0.0, 1.0};
|
double(rect.size[0]), double(rect.size[1]), 0.0, 1.0};
|
||||||
[m_enc setViewport:vp];
|
[m_enc setViewport:vp];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScissor(const SWindowRect& rect)
|
void setScissor(const SWindowRect& rect)
|
||||||
{
|
{
|
||||||
if (m_boundTarget)
|
if (m_boundTarget)
|
||||||
|
@ -612,7 +617,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
[m_enc setScissorRect:scissor];
|
[m_enc setScissorRect:scissor];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -624,9 +629,9 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
||||||
void flushBufferUpdates() {}
|
void flushBufferUpdates() {}
|
||||||
|
|
||||||
float m_clearColor[4] = {0.0,0.0,0.0,1.0};
|
float m_clearColor[4] = {0.0,0.0,0.0,1.0};
|
||||||
void setClearColor(const float rgba[4])
|
void setClearColor(const float rgba[4])
|
||||||
{
|
{
|
||||||
|
@ -635,14 +640,14 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
m_clearColor[2] = rgba[2];
|
m_clearColor[2] = rgba[2];
|
||||||
m_clearColor[3] = rgba[3];
|
m_clearColor[3] = rgba[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearTarget(bool render=true, bool depth=true)
|
void clearTarget(bool render=true, bool depth=true)
|
||||||
{
|
{
|
||||||
if (!m_boundTarget)
|
if (!m_boundTarget)
|
||||||
return;
|
return;
|
||||||
setRenderTarget(m_boundTarget);
|
setRenderTarget(m_boundTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTLPrimitiveType m_primType = MTLPrimitiveTypeTriangle;
|
MTLPrimitiveType m_primType = MTLPrimitiveTypeTriangle;
|
||||||
void setDrawPrimitive(Primitive prim)
|
void setDrawPrimitive(Primitive prim)
|
||||||
{
|
{
|
||||||
|
@ -651,12 +656,12 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
else if (prim == Primitive::TriStrips)
|
else if (prim == Primitive::TriStrips)
|
||||||
m_primType = MTLPrimitiveTypeTriangleStrip;
|
m_primType = MTLPrimitiveTypeTriangleStrip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(size_t start, size_t count)
|
void draw(size_t start, size_t count)
|
||||||
{
|
{
|
||||||
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count];
|
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count];
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawIndexed(size_t start, size_t count)
|
void drawIndexed(size_t start, size_t count)
|
||||||
{
|
{
|
||||||
[m_enc drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
|
@ -665,12 +670,12 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
||||||
indexBufferOffset:start*4];
|
indexBufferOffset:start*4];
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawInstances(size_t start, size_t count, size_t instCount)
|
void drawInstances(size_t start, size_t count, size_t instCount)
|
||||||
{
|
{
|
||||||
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count instanceCount:instCount];
|
[m_enc drawPrimitives:m_primType vertexStart:start vertexCount:count instanceCount:instCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawInstancesIndexed(size_t start, size_t count, size_t instCount)
|
void drawInstancesIndexed(size_t start, size_t count, size_t instCount)
|
||||||
{
|
{
|
||||||
[m_enc drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
|
@ -680,19 +685,19 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
indexBufferOffset:start*4
|
indexBufferOffset:start*4
|
||||||
instanceCount:instCount];
|
instanceCount:instCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalTextureR* m_needsDisplay = nullptr;
|
MetalTextureR* m_needsDisplay = nullptr;
|
||||||
void resolveDisplay(ITextureR* source)
|
void resolveDisplay(ITextureR* source)
|
||||||
{
|
{
|
||||||
m_needsDisplay = static_cast<MetalTextureR*>(source);
|
m_needsDisplay = static_cast<MetalTextureR*>(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_inProgress = false;
|
bool m_inProgress = false;
|
||||||
void execute()
|
void execute()
|
||||||
{
|
{
|
||||||
if (!m_running)
|
if (!m_running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Update dynamic data here */
|
/* Update dynamic data here */
|
||||||
MetalDataFactory* gfxF = static_cast<MetalDataFactory*>(m_parent->getDataFactory());
|
MetalDataFactory* gfxF = static_cast<MetalDataFactory*>(m_parent->getDataFactory());
|
||||||
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
std::unique_lock<std::mutex> datalk(gfxF->m_committedMutex);
|
||||||
|
@ -704,19 +709,19 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
t->update(m_fillBuf);
|
t->update(m_fillBuf);
|
||||||
}
|
}
|
||||||
datalk.unlock();
|
datalk.unlock();
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[m_enc endEncoding];
|
[m_enc endEncoding];
|
||||||
m_enc = nullptr;
|
m_enc = nullptr;
|
||||||
|
|
||||||
/* Abandon if in progress (renderer too slow) */
|
/* Abandon if in progress (renderer too slow) */
|
||||||
if (m_inProgress)
|
if (m_inProgress)
|
||||||
{
|
{
|
||||||
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform texture resizes */
|
/* Perform texture resizes */
|
||||||
if (m_texResizes.size())
|
if (m_texResizes.size())
|
||||||
{
|
{
|
||||||
|
@ -726,7 +731,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrap up and present if needed */
|
/* Wrap up and present if needed */
|
||||||
if (m_needsDisplay)
|
if (m_needsDisplay)
|
||||||
{
|
{
|
||||||
|
@ -767,10 +772,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
m_needsDisplay = nullptr;
|
m_needsDisplay = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_drawBuf = m_fillBuf;
|
m_drawBuf = m_fillBuf;
|
||||||
m_fillBuf ^= 1;
|
m_fillBuf ^= 1;
|
||||||
|
|
||||||
[m_cmdBuf addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
[m_cmdBuf addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
||||||
m_inProgress = true;
|
m_inProgress = true;
|
||||||
[m_cmdBuf commit];
|
[m_cmdBuf commit];
|
||||||
|
@ -778,7 +783,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void MetalGraphicsBufferD::update(int b)
|
void MetalGraphicsBufferD::update(int b)
|
||||||
{
|
{
|
||||||
int slot = 1 << b;
|
int slot = 1 << b;
|
||||||
|
@ -833,10 +838,10 @@ void MetalTextureD::unmap()
|
||||||
{
|
{
|
||||||
m_validSlots = 0;
|
m_validSlots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
|
MetalDataFactory::MetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
|
||||||
: m_parent(parent), m_ctx(ctx) {}
|
: m_parent(parent), m_ctx(ctx) {}
|
||||||
|
|
||||||
IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
|
IGraphicsBufferS* MetalDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
|
||||||
{
|
{
|
||||||
MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(use, m_ctx, data, stride, count);
|
MetalGraphicsBufferS* retval = new MetalGraphicsBufferS(use, m_ctx, data, stride, count);
|
||||||
|
@ -873,15 +878,18 @@ ITextureS* MetalDataFactory::newStaticTexture(size_t width, size_t height, size_
|
||||||
m_deferredData->m_STexs.emplace_back(retval);
|
m_deferredData->m_STexs.emplace_back(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
ITextureS* MetalDataFactory::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
GraphicsDataToken
|
||||||
std::unique_ptr<uint8_t[]>&& data, size_t sz)
|
MetalDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
|
||||||
|
const void* data, size_t sz, ITextureS** texOut)
|
||||||
{
|
{
|
||||||
std::unique_ptr<uint8_t[]> d = std::move(data);
|
MetalTextureS* retval = new MetalTextureS(m_ctx, width, height, mips, fmt, data, sz);
|
||||||
MetalTextureS* retval = new MetalTextureS(m_ctx, width, height, mips, fmt, d.get(), sz);
|
MetalData* tokData = new struct MetalData();
|
||||||
if (!m_deferredData.get())
|
tokData->m_STexs.emplace_back(retval);
|
||||||
m_deferredData.reset(new struct MetalData());
|
*texOut = retval;
|
||||||
m_deferredData->m_STexs.emplace_back(retval);
|
|
||||||
return retval;
|
std::unique_lock<std::mutex> lk(m_committedMutex);
|
||||||
|
m_committedData.insert(tokData);
|
||||||
|
return GraphicsDataToken(this, tokData);
|
||||||
}
|
}
|
||||||
ITextureSA* MetalDataFactory::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
|
ITextureSA* MetalDataFactory::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
|
||||||
const void* data, size_t sz)
|
const void* data, size_t sz)
|
||||||
|
@ -927,21 +935,21 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
|
||||||
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||||
compOpts.languageVersion = MTLLanguageVersion1_1;
|
compOpts.languageVersion = MTLLanguageVersion1_1;
|
||||||
NSError* err = nullptr;
|
NSError* err = nullptr;
|
||||||
|
|
||||||
id<MTLLibrary> vertShaderLib = [m_ctx->m_dev newLibraryWithSource:@(vertSource)
|
id<MTLLibrary> vertShaderLib = [m_ctx->m_dev newLibraryWithSource:@(vertSource)
|
||||||
options:compOpts
|
options:compOpts
|
||||||
error:&err];
|
error:&err];
|
||||||
if (err)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]);
|
Log.report(LogVisor::FatalError, "error compiling vert shader: %s", [[err localizedDescription] UTF8String]);
|
||||||
id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"];
|
id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"];
|
||||||
|
|
||||||
id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource)
|
id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource)
|
||||||
options:compOpts
|
options:compOpts
|
||||||
error:&err];
|
error:&err];
|
||||||
if (err)
|
if (err)
|
||||||
Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]);
|
Log.report(LogVisor::FatalError, "error compiling frag shader: %s", [[err localizedDescription] UTF8String]);
|
||||||
id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"];
|
id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"];
|
||||||
|
|
||||||
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc,
|
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc, fragFunc,
|
||||||
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
|
static_cast<const MetalVertexFormat*>(vtxFmt), targetSamples,
|
||||||
srcFac, dstFac, depthTest, depthWrite, backfaceCulling);
|
srcFac, dstFac, depthTest, depthWrite, backfaceCulling);
|
||||||
|
@ -995,13 +1003,13 @@ void MetalDataFactory::destroyAllData()
|
||||||
delete static_cast<MetalData*>(data);
|
delete static_cast<MetalData*>(data);
|
||||||
m_committedData.clear();
|
m_committedData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
||||||
IGraphicsContext* parent)
|
IGraphicsContext* parent)
|
||||||
{
|
{
|
||||||
return new struct MetalCommandQueue(ctx, parentWindow, parent);
|
return new struct MetalCommandQueue(ctx, parentWindow, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue