mirror of https://github.com/AxioDL/boo.git
NSPtr is unnecessary with ARC enabled
This commit is contained in:
parent
5550909f7e
commit
9b416c6549
|
@ -41,13 +41,13 @@ class MetalGraphicsBufferS : public IGraphicsBufferS
|
||||||
MetalGraphicsBufferS(BufferUse use, MetalContext* ctx, const void* data, size_t stride, size_t count)
|
MetalGraphicsBufferS(BufferUse use, MetalContext* ctx, const void* data, size_t stride, size_t count)
|
||||||
: m_stride(stride), m_count(count), m_sz(stride * count)
|
: m_stride(stride), m_count(count), m_sz(stride * count)
|
||||||
{
|
{
|
||||||
m_buf = [ctx->m_dev.get() newBufferWithBytes:data length:m_sz options:MTL_STATIC];
|
m_buf = [ctx->m_dev newBufferWithBytes:data length:m_sz options:MTL_STATIC];
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
size_t m_stride;
|
size_t m_stride;
|
||||||
size_t m_count;
|
size_t m_count;
|
||||||
size_t m_sz;
|
size_t m_sz;
|
||||||
NSPtr<id<MTLBuffer>> m_buf;
|
id<MTLBuffer> m_buf;
|
||||||
~MetalGraphicsBufferS() = default;
|
~MetalGraphicsBufferS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,15 +62,15 @@ class MetalGraphicsBufferD : public IGraphicsBufferD
|
||||||
: 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_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 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 newBufferWithLength:m_sz options:MTL_DYNAMIC];
|
||||||
}
|
}
|
||||||
void update(int b);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
size_t m_stride;
|
size_t m_stride;
|
||||||
size_t m_count;
|
size_t m_count;
|
||||||
size_t m_sz;
|
size_t m_sz;
|
||||||
NSPtr<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);
|
||||||
|
@ -95,30 +95,30 @@ class MetalTextureS : public ITextureS
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
MTLTextureDescriptor* desc =
|
||||||
width:width height:height
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||||
mipmapped:(mips>1)?YES:NO];
|
width:width height:height
|
||||||
}
|
mipmapped:(mips>1)?YES:NO];
|
||||||
desc.get().usage = MTLTextureUsageShaderRead;
|
desc.usage = MTLTextureUsageShaderRead;
|
||||||
desc.get().mipmapLevelCount = mips;
|
desc.mipmapLevelCount = mips;
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||||
for (size_t i=0 ; i<mips ; ++i)
|
for (size_t i=0 ; i<mips ; ++i)
|
||||||
{
|
{
|
||||||
[m_tex.get() 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 * ppitch];
|
||||||
dataIt += width * height * ppitch;
|
dataIt += width * height * ppitch;
|
||||||
width /= 2;
|
width /= 2;
|
||||||
height /= 2;
|
height /= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureS() = default;
|
~MetalTextureS() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,31 +139,31 @@ class MetalTextureSA : public ITextureSA
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
MTLTextureDescriptor* desc =
|
||||||
width:width height:height
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pfmt
|
||||||
mipmapped:NO];
|
width:width height:height
|
||||||
}
|
mipmapped:NO];
|
||||||
desc.get().textureType = MTLTextureType2DArray;
|
desc.textureType = MTLTextureType2DArray;
|
||||||
desc.get().arrayLength = layers;
|
desc.arrayLength = layers;
|
||||||
desc.get().usage = MTLTextureUsageShaderRead;
|
desc.usage = MTLTextureUsageShaderRead;
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
const uint8_t* dataIt = reinterpret_cast<const uint8_t*>(data);
|
||||||
for (size_t i=0 ; i<layers ; ++i)
|
for (size_t i=0 ; i<layers ; ++i)
|
||||||
{
|
{
|
||||||
[m_tex.get() replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
[m_tex replaceRegion:MTLRegionMake2D(0, 0, width, height)
|
||||||
mipmapLevel:0
|
mipmapLevel:0
|
||||||
slice:i
|
slice:i
|
||||||
withBytes:dataIt
|
withBytes:dataIt
|
||||||
bytesPerRow:width * ppitch
|
bytesPerRow:width * ppitch
|
||||||
bytesPerImage:width * height * ppitch];
|
bytesPerImage:width * height * ppitch];
|
||||||
dataIt += width * height * ppitch;
|
dataIt += width * height * ppitch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
~MetalTextureSA() = default;
|
~MetalTextureSA() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,20 +199,20 @@ class MetalTextureD : public ITextureD
|
||||||
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]);
|
||||||
|
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
MTLTextureDescriptor* desc =
|
||||||
width:width height:height
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||||
mipmapped:NO];
|
width:width height:height
|
||||||
|
mipmapped:NO];
|
||||||
|
desc.usage = MTLTextureUsageShaderRead;
|
||||||
|
m_texs[0] = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
m_texs[1] = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
}
|
}
|
||||||
desc.get().usage = MTLTextureUsageShaderRead;
|
|
||||||
m_texs[0] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
|
||||||
m_texs[1] = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
|
||||||
}
|
}
|
||||||
void update(int b);
|
void update(int b);
|
||||||
public:
|
public:
|
||||||
NSPtr<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);
|
||||||
|
@ -230,49 +230,49 @@ class MetalTextureR : public ITextureR
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
NSPtr<MTLTextureDescriptor*> desc;
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
MTLTextureDescriptor* desc =
|
||||||
width:width height:height
|
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
|
||||||
mipmapped:NO];
|
width:width height:height
|
||||||
|
mipmapped:NO];
|
||||||
m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
m_passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||||
}
|
desc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
||||||
desc.get().usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
|
desc.storageMode = MTLStorageModePrivate;
|
||||||
desc.get().storageMode = MTLStorageModePrivate;
|
|
||||||
|
|
||||||
m_tex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_tex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
if (samples > 1)
|
if (samples > 1)
|
||||||
{
|
{
|
||||||
desc.get().textureType = MTLTextureType2DMultisample;
|
desc.textureType = MTLTextureType2DMultisample;
|
||||||
desc.get().sampleCount = samples;
|
desc.sampleCount = samples;
|
||||||
m_msaaTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_msaaTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
m_passDesc.get().colorAttachments[0].texture = m_msaaTex.get();
|
m_passDesc.colorAttachments[0].texture = m_msaaTex;
|
||||||
m_passDesc.get().colorAttachments[0].resolveTexture = m_tex.get();
|
m_passDesc.colorAttachments[0].resolveTexture = m_tex;
|
||||||
m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear;
|
m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
|
m_passDesc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
|
||||||
|
|
||||||
m_passDesc.get().depthAttachment.texture = m_depthTex.get();
|
m_passDesc.depthAttachment.texture = m_depthTex;
|
||||||
m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear;
|
m_passDesc.depthAttachment.loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare;
|
m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
desc.get().pixelFormat = MTLPixelFormatDepth32Float;
|
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||||
m_depthTex = [ctx->m_dev.get() newTextureWithDescriptor:desc.get()];
|
m_depthTex = [ctx->m_dev newTextureWithDescriptor:desc];
|
||||||
|
|
||||||
m_passDesc.get().colorAttachments[0].texture = m_tex.get();
|
m_passDesc.colorAttachments[0].texture = m_tex;
|
||||||
m_passDesc.get().colorAttachments[0].loadAction = MTLLoadActionClear;
|
m_passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().colorAttachments[0].storeAction = MTLStoreActionStore;
|
m_passDesc.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||||
|
|
||||||
m_passDesc.get().depthAttachment.texture = m_depthTex.get();
|
m_passDesc.depthAttachment.texture = m_depthTex;
|
||||||
m_passDesc.get().depthAttachment.loadAction = MTLLoadActionClear;
|
m_passDesc.depthAttachment.loadAction = MTLLoadActionClear;
|
||||||
m_passDesc.get().depthAttachment.storeAction = MTLStoreActionDontCare;
|
m_passDesc.depthAttachment.storeAction = MTLStoreActionDontCare;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,10 +284,10 @@ class MetalTextureR : public ITextureR
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
size_t samples() const {return m_samples;}
|
size_t samples() const {return m_samples;}
|
||||||
NSPtr<id<MTLTexture>> m_tex;
|
id<MTLTexture> m_tex;
|
||||||
NSPtr<id<MTLTexture>> m_msaaTex;
|
id<MTLTexture> m_msaaTex;
|
||||||
NSPtr<id<MTLTexture>> m_depthTex;
|
id<MTLTexture> m_depthTex;
|
||||||
NSPtr<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)
|
||||||
|
@ -301,7 +301,7 @@ public:
|
||||||
Setup(ctx, width, height, m_samples);
|
Setup(ctx, width, height, m_samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
id<MTLTexture> getRenderColorRes() {if (m_samples > 1) return m_msaaTex.get(); return m_tex.get();}
|
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[] =
|
||||||
|
@ -337,7 +337,7 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] =
|
||||||
struct MetalVertexFormat : IVertexFormat
|
struct MetalVertexFormat : IVertexFormat
|
||||||
{
|
{
|
||||||
size_t m_elementCount;
|
size_t m_elementCount;
|
||||||
NSPtr<MTLVertexDescriptor*> m_vdesc;
|
MTLVertexDescriptor* m_vdesc;
|
||||||
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||||
: m_elementCount(elementCount)
|
: m_elementCount(elementCount)
|
||||||
{
|
{
|
||||||
|
@ -354,12 +354,12 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vdesc = [MTLVertexDescriptor vertexDescriptor];
|
m_vdesc = [MTLVertexDescriptor vertexDescriptor];
|
||||||
MTLVertexBufferLayoutDescriptor* layoutDesc = m_vdesc.get().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.get().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;
|
||||||
|
@ -369,7 +369,7 @@ struct MetalVertexFormat : IVertexFormat
|
||||||
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];
|
||||||
MTLVertexAttributeDescriptor* attrDesc = m_vdesc.get().attributes[i];
|
MTLVertexAttributeDescriptor* attrDesc = m_vdesc.attributes[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)
|
||||||
{
|
{
|
||||||
|
@ -415,40 +415,40 @@ class MetalShaderPipeline : public IShaderPipeline
|
||||||
if (backfaceCulling)
|
if (backfaceCulling)
|
||||||
m_cullMode = MTLCullModeBack;
|
m_cullMode = MTLCullModeBack;
|
||||||
|
|
||||||
NSPtr<MTLRenderPipelineDescriptor*> desc = [MTLRenderPipelineDescriptor new];
|
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
||||||
desc.get().vertexFunction = vert;
|
desc.vertexFunction = vert;
|
||||||
desc.get().fragmentFunction = frag;
|
desc.fragmentFunction = frag;
|
||||||
desc.get().vertexDescriptor = vtxFmt->m_vdesc.get();
|
desc.vertexDescriptor = vtxFmt->m_vdesc;
|
||||||
desc.get().sampleCount = targetSamples;
|
desc.sampleCount = targetSamples;
|
||||||
desc.get().colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
desc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
desc.get().colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
|
desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
|
||||||
desc.get().colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
||||||
desc.get().colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
||||||
desc.get().depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
desc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float;
|
||||||
desc.get().inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
||||||
NSError* err = nullptr;
|
NSError* err = nullptr;
|
||||||
m_state = [ctx->m_dev.get() newRenderPipelineStateWithDescriptor:desc.get() error:&err];
|
m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err];
|
||||||
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]);
|
||||||
|
|
||||||
NSPtr<MTLDepthStencilDescriptor*> dsDesc = [MTLDepthStencilDescriptor new];
|
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
|
||||||
if (depthTest)
|
if (depthTest)
|
||||||
dsDesc.get().depthCompareFunction = MTLCompareFunctionLessEqual;
|
dsDesc.depthCompareFunction = MTLCompareFunctionLessEqual;
|
||||||
dsDesc.get().depthWriteEnabled = depthWrite;
|
dsDesc.depthWriteEnabled = depthWrite;
|
||||||
m_dsState = [ctx->m_dev.get() newDepthStencilStateWithDescriptor:dsDesc.get()];
|
m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc];
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NSPtr<id<MTLRenderPipelineState>> m_state;
|
id<MTLRenderPipelineState> m_state;
|
||||||
NSPtr<id<MTLDepthStencilState>> m_dsState;
|
id<MTLDepthStencilState> m_dsState;
|
||||||
~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.get()];
|
[enc setRenderPipelineState:m_state];
|
||||||
[enc setDepthStencilState:m_dsState.get()];
|
[enc setDepthStencilState:m_dsState];
|
||||||
[enc setCullMode:m_cullMode];
|
[enc setCullMode:m_cullMode];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -458,12 +458,12 @@ static id<MTLBuffer> GetBufferGPUResource(const IGraphicsBuffer* buf, int idx)
|
||||||
if (buf->dynamic())
|
if (buf->dynamic())
|
||||||
{
|
{
|
||||||
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
|
const MetalGraphicsBufferD* cbuf = static_cast<const MetalGraphicsBufferD*>(buf);
|
||||||
return cbuf->m_bufs[idx].get();
|
return cbuf->m_bufs[idx];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const MetalGraphicsBufferS* cbuf = static_cast<const MetalGraphicsBufferS*>(buf);
|
const MetalGraphicsBufferS* cbuf = static_cast<const MetalGraphicsBufferS*>(buf);
|
||||||
return cbuf->m_buf.get();
|
return cbuf->m_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,22 +474,22 @@ static id<MTLTexture> GetTextureGPUResource(const ITexture* tex, int idx)
|
||||||
case TextureType::Dynamic:
|
case TextureType::Dynamic:
|
||||||
{
|
{
|
||||||
const MetalTextureD* ctex = static_cast<const MetalTextureD*>(tex);
|
const MetalTextureD* ctex = static_cast<const MetalTextureD*>(tex);
|
||||||
return ctex->m_texs[idx].get();
|
return ctex->m_texs[idx];
|
||||||
}
|
}
|
||||||
case TextureType::Static:
|
case TextureType::Static:
|
||||||
{
|
{
|
||||||
const MetalTextureS* ctex = static_cast<const MetalTextureS*>(tex);
|
const MetalTextureS* ctex = static_cast<const MetalTextureS*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
case TextureType::StaticArray:
|
case TextureType::StaticArray:
|
||||||
{
|
{
|
||||||
const MetalTextureSA* ctex = static_cast<const MetalTextureSA*>(tex);
|
const MetalTextureSA* ctex = static_cast<const MetalTextureSA*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
case TextureType::Render:
|
case TextureType::Render:
|
||||||
{
|
{
|
||||||
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex);
|
const MetalTextureR* ctex = static_cast<const MetalTextureR*>(tex);
|
||||||
return ctex->m_tex.get();
|
return ctex->m_tex;
|
||||||
}
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -547,8 +547,8 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
MetalContext* m_ctx;
|
MetalContext* m_ctx;
|
||||||
IWindow* m_parentWindow;
|
IWindow* m_parentWindow;
|
||||||
IGraphicsContext* m_parent;
|
IGraphicsContext* m_parent;
|
||||||
NSPtr<id<MTLCommandBuffer>> m_cmdBuf;
|
id<MTLCommandBuffer> m_cmdBuf;
|
||||||
NSPtr<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;
|
||||||
|
@ -559,7 +559,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
m_cmdBuf = [ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [ctx->m_q commandBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -567,7 +567,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
if (m_inProgress)
|
if (m_inProgress)
|
||||||
[m_cmdBuf.get() waitUntilCompleted];
|
[m_cmdBuf waitUntilCompleted];
|
||||||
}
|
}
|
||||||
|
|
||||||
~MetalCommandQueue()
|
~MetalCommandQueue()
|
||||||
|
@ -579,7 +579,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
void setShaderDataBinding(IShaderDataBinding* binding)
|
void setShaderDataBinding(IShaderDataBinding* binding)
|
||||||
{
|
{
|
||||||
MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding);
|
MetalShaderDataBinding* cbind = static_cast<MetalShaderDataBinding*>(binding);
|
||||||
cbind->bind(m_enc.get(), m_fillBuf);
|
cbind->bind(m_enc, m_fillBuf);
|
||||||
m_boundData = cbind;
|
m_boundData = cbind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,10 +587,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
void setRenderTarget(ITextureR* target)
|
void setRenderTarget(ITextureR* target)
|
||||||
{
|
{
|
||||||
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
|
MetalTextureR* ctarget = static_cast<MetalTextureR*>(target);
|
||||||
[m_enc.get() endEncoding];
|
[m_enc endEncoding];
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
m_enc = [m_cmdBuf.get() renderCommandEncoderWithDescriptor:ctarget->m_passDesc.get()];
|
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:ctarget->m_passDesc];
|
||||||
}
|
}
|
||||||
m_boundTarget = ctarget;
|
m_boundTarget = ctarget;
|
||||||
}
|
}
|
||||||
|
@ -599,7 +599,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
{
|
{
|
||||||
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.get() setViewport:vp];
|
[m_enc setViewport:vp];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setScissor(const SWindowRect& rect)
|
void setScissor(const SWindowRect& rect)
|
||||||
|
@ -609,7 +609,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
MTLScissorRect scissor = {NSUInteger(rect.location[0]),
|
MTLScissorRect scissor = {NSUInteger(rect.location[0]),
|
||||||
NSUInteger(m_boundTarget->m_height - rect.location[1] - rect.size[1]),
|
NSUInteger(m_boundTarget->m_height - rect.location[1] - rect.size[1]),
|
||||||
NSUInteger(rect.size[0]), NSUInteger(rect.size[1])};
|
NSUInteger(rect.size[0]), NSUInteger(rect.size[1])};
|
||||||
[m_enc.get() setScissorRect:scissor];
|
[m_enc setScissorRect:scissor];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,31 +654,31 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
void draw(size_t start, size_t count)
|
void draw(size_t start, size_t count)
|
||||||
{
|
{
|
||||||
[m_enc.get() 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.get() drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
indexCount:count
|
indexCount:count
|
||||||
indexType:MTLIndexTypeUInt32
|
indexType:MTLIndexTypeUInt32
|
||||||
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.get() 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.get() drawIndexedPrimitives:m_primType
|
[m_enc drawIndexedPrimitives:m_primType
|
||||||
indexCount:count
|
indexCount:count
|
||||||
indexType:MTLIndexTypeUInt32
|
indexType:MTLIndexTypeUInt32
|
||||||
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
indexBuffer:GetBufferGPUResource(m_boundData->m_ibuf, m_fillBuf)
|
||||||
indexBufferOffset:start*4
|
indexBufferOffset:start*4
|
||||||
instanceCount:instCount];
|
instanceCount:instCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalTextureR* m_needsDisplay = nullptr;
|
MetalTextureR* m_needsDisplay = nullptr;
|
||||||
|
@ -707,13 +707,13 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
[m_enc.get() endEncoding];
|
[m_enc endEncoding];
|
||||||
m_enc.reset();
|
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.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +723,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
for (const auto& resize : m_texResizes)
|
for (const auto& resize : m_texResizes)
|
||||||
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
|
resize.first->resize(m_ctx, resize.second.first, resize.second.second);
|
||||||
m_texResizes.clear();
|
m_texResizes.clear();
|
||||||
m_cmdBuf = [m_ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,11 +747,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
if (drawable)
|
if (drawable)
|
||||||
{
|
{
|
||||||
id<MTLTexture> dest = drawable.texture;
|
id<MTLTexture> dest = drawable.texture;
|
||||||
if (m_needsDisplay->m_tex.get().width == dest.width &&
|
if (m_needsDisplay->m_tex.width == dest.width &&
|
||||||
m_needsDisplay->m_tex.get().height == dest.height)
|
m_needsDisplay->m_tex.height == dest.height)
|
||||||
{
|
{
|
||||||
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf.get() blitCommandEncoder];
|
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
|
||||||
[blitEnc copyFromTexture:m_needsDisplay->m_tex.get()
|
[blitEnc copyFromTexture:m_needsDisplay->m_tex
|
||||||
sourceSlice:0
|
sourceSlice:0
|
||||||
sourceLevel:0
|
sourceLevel:0
|
||||||
sourceOrigin:MTLOriginMake(0, 0, 0)
|
sourceOrigin:MTLOriginMake(0, 0, 0)
|
||||||
|
@ -761,7 +761,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
destinationLevel:0
|
destinationLevel:0
|
||||||
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
destinationOrigin:MTLOriginMake(0, 0, 0)];
|
||||||
[blitEnc endEncoding];
|
[blitEnc endEncoding];
|
||||||
[m_cmdBuf.get() presentDrawable:drawable];
|
[m_cmdBuf presentDrawable:drawable];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -771,10 +771,10 @@ struct MetalCommandQueue : IGraphicsCommandQueue
|
||||||
m_drawBuf = m_fillBuf;
|
m_drawBuf = m_fillBuf;
|
||||||
m_fillBuf ^= 1;
|
m_fillBuf ^= 1;
|
||||||
|
|
||||||
[m_cmdBuf.get() addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
[m_cmdBuf addCompletedHandler:^(id<MTLCommandBuffer> buf) {m_inProgress = false;}];
|
||||||
m_inProgress = true;
|
m_inProgress = true;
|
||||||
[m_cmdBuf.get() commit];
|
[m_cmdBuf commit];
|
||||||
m_cmdBuf = [m_ctx->m_q.get() commandBuffer];
|
m_cmdBuf = [m_ctx->m_q commandBuffer];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -784,7 +784,7 @@ void MetalGraphicsBufferD::update(int b)
|
||||||
int slot = 1 << b;
|
int slot = 1 << b;
|
||||||
if ((slot & m_validSlots) == 0)
|
if ((slot & m_validSlots) == 0)
|
||||||
{
|
{
|
||||||
id<MTLBuffer> res = m_bufs[b].get();
|
id<MTLBuffer> res = m_bufs[b];
|
||||||
memcpy(res.contents, m_cpuBuf.get(), m_sz);
|
memcpy(res.contents, m_cpuBuf.get(), m_sz);
|
||||||
m_validSlots |= slot;
|
m_validSlots |= slot;
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,7 @@ void MetalTextureD::update(int b)
|
||||||
int slot = 1 << b;
|
int slot = 1 << b;
|
||||||
if ((slot & m_validSlots) == 0)
|
if ((slot & m_validSlots) == 0)
|
||||||
{
|
{
|
||||||
id<MTLTexture> res = m_texs[b].get();
|
id<MTLTexture> res = m_texs[b];
|
||||||
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
[res replaceRegion:MTLRegionMake2D(0, 0, m_width, m_height)
|
||||||
mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch];
|
mipmapLevel:0 withBytes:m_cpuBuf.get() bytesPerRow:m_width*m_pxPitch];
|
||||||
m_validSlots |= slot;
|
m_validSlots |= slot;
|
||||||
|
@ -924,25 +924,25 @@ IShaderPipeline* MetalDataFactory::newShaderPipeline(const char* vertSource, con
|
||||||
BlendFactor srcFac, BlendFactor dstFac,
|
BlendFactor srcFac, BlendFactor dstFac,
|
||||||
bool depthTest, bool depthWrite, bool backfaceCulling)
|
bool depthTest, bool depthWrite, bool backfaceCulling)
|
||||||
{
|
{
|
||||||
NSPtr<MTLCompileOptions*> compOpts = [MTLCompileOptions new];
|
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||||
compOpts.get().languageVersion = MTLLanguageVersion1_1;
|
compOpts.languageVersion = MTLLanguageVersion1_1;
|
||||||
NSError* err = nullptr;
|
NSError* err = nullptr;
|
||||||
|
|
||||||
NSPtr<id<MTLLibrary>> vertShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(vertSource)
|
id<MTLLibrary> vertShaderLib = [m_ctx->m_dev newLibraryWithSource:@(vertSource)
|
||||||
options:compOpts.get()
|
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]);
|
||||||
NSPtr<id<MTLFunction>> vertFunc = [vertShaderLib.get() newFunctionWithName:@"vmain"];
|
id<MTLFunction> vertFunc = [vertShaderLib newFunctionWithName:@"vmain"];
|
||||||
|
|
||||||
NSPtr<id<MTLLibrary>> fragShaderLib = [m_ctx->m_dev.get() newLibraryWithSource:@(fragSource)
|
id<MTLLibrary> fragShaderLib = [m_ctx->m_dev newLibraryWithSource:@(fragSource)
|
||||||
options:compOpts.get()
|
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]);
|
||||||
NSPtr<id<MTLFunction>> fragFunc = [fragShaderLib.get() newFunctionWithName:@"fmain"];
|
id<MTLFunction> fragFunc = [fragShaderLib newFunctionWithName:@"fmain"];
|
||||||
|
|
||||||
MetalShaderPipeline* retval = new MetalShaderPipeline(m_ctx, vertFunc.get(), fragFunc.get(),
|
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);
|
||||||
if (!m_deferredData.get())
|
if (!m_deferredData.get())
|
||||||
|
|
|
@ -89,7 +89,7 @@ public:
|
||||||
if (!arg.compare("--metal"))
|
if (!arg.compare("--metal"))
|
||||||
{
|
{
|
||||||
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
||||||
m_metalCtx.m_q = [m_metalCtx.m_dev.get() newCommandQueue];
|
m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue];
|
||||||
Log.report(LogVisor::Info, "using Metal renderer");
|
Log.report(LogVisor::Info, "using Metal renderer");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,40 +7,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Availability.h>
|
#include <Availability.h>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class NSPtr
|
|
||||||
{
|
|
||||||
void* m_ptr = nullptr;
|
|
||||||
public:
|
|
||||||
NSPtr() = default;
|
|
||||||
~NSPtr()
|
|
||||||
{
|
|
||||||
T ptr = (__bridge_transfer T)m_ptr;
|
|
||||||
(void)ptr;
|
|
||||||
}
|
|
||||||
NSPtr(T&& recv) {*this = std::move(recv);}
|
|
||||||
NSPtr& operator=(T&& recv)
|
|
||||||
{
|
|
||||||
T old = (__bridge_transfer T)m_ptr;
|
|
||||||
(void)old;
|
|
||||||
m_ptr = (__bridge_retained void*)recv;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
NSPtr(const NSPtr& other) = delete;
|
|
||||||
NSPtr(NSPtr&& other) = default;
|
|
||||||
NSPtr& operator=(const NSPtr& other) = delete;
|
|
||||||
NSPtr& operator=(NSPtr&& other) = default;
|
|
||||||
operator bool() const {return m_ptr != 0;}
|
|
||||||
T get() const {return (__bridge T)m_ptr;}
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
T old = (__bridge_transfer T)m_ptr;
|
|
||||||
(void)old;
|
|
||||||
m_ptr = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||||
#define BOO_HAS_METAL 1
|
#define BOO_HAS_METAL 1
|
||||||
|
@ -55,8 +21,8 @@ namespace boo
|
||||||
class IWindow;
|
class IWindow;
|
||||||
struct MetalContext
|
struct MetalContext
|
||||||
{
|
{
|
||||||
NSPtr<id<MTLDevice>> m_dev;
|
id<MTLDevice> m_dev = nullptr;
|
||||||
NSPtr<id<MTLCommandQueue>> m_q;
|
id<MTLCommandQueue> m_q = nullptr;
|
||||||
struct Window
|
struct Window
|
||||||
{
|
{
|
||||||
CAMetalLayer* m_metalLayer = nullptr;
|
CAMetalLayer* m_metalLayer = nullptr;
|
||||||
|
|
|
@ -1154,7 +1154,7 @@ static boo::ESpecialKey translateKeycode(short code)
|
||||||
- (CALayer*)makeBackingLayer
|
- (CALayer*)makeBackingLayer
|
||||||
{
|
{
|
||||||
CAMetalLayer* layer = [CAMetalLayer new];
|
CAMetalLayer* layer = [CAMetalLayer new];
|
||||||
layer.device = m_ctx->m_dev.get();
|
layer.device = m_ctx->m_dev;
|
||||||
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||||
layer.framebufferOnly = NO;
|
layer.framebufferOnly = NO;
|
||||||
return layer;
|
return layer;
|
||||||
|
|
Loading…
Reference in New Issue