Metal: Added swap chain support. Manual merge from PR #1563.
This commit is contained in:
parent
610d503d97
commit
2b919c1ec4
@ -888,6 +888,35 @@ namespace bgfx { namespace mtl
|
||||
uint8_t m_numMips;
|
||||
};
|
||||
|
||||
struct FrameBufferMtl;
|
||||
|
||||
struct SwapChainMtl
|
||||
{
|
||||
SwapChainMtl()
|
||||
: m_metalLayer(nil)
|
||||
, m_drawable(nil)
|
||||
, m_backBufferColorMSAA()
|
||||
, m_backBufferDepth()
|
||||
, m_backBufferStencil()
|
||||
, m_maxAnisotropy(0)
|
||||
{
|
||||
}
|
||||
|
||||
~SwapChainMtl();
|
||||
|
||||
void init(void* _nwh);
|
||||
void resize(FrameBufferMtl &_frameBuffer, uint32_t _width, uint32_t _height, uint32_t _flags);
|
||||
|
||||
id<CAMetalDrawable> currentDrawable();
|
||||
|
||||
CAMetalLayer* m_metalLayer;
|
||||
id <CAMetalDrawable> m_drawable;
|
||||
Texture m_backBufferColorMSAA;
|
||||
Texture m_backBufferDepth;
|
||||
Texture m_backBufferStencil;
|
||||
uint32_t m_maxAnisotropy;
|
||||
};
|
||||
|
||||
struct FrameBufferMtl
|
||||
{
|
||||
FrameBufferMtl()
|
||||
@ -910,6 +939,7 @@ namespace bgfx { namespace mtl
|
||||
void postReset();
|
||||
uint16_t destroy();
|
||||
|
||||
SwapChainMtl* m_swapChain;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint16_t m_denseIdx;
|
||||
|
@ -46,7 +46,6 @@ Known issues(driver problems??):
|
||||
|
||||
- finish savescreenshot with screenshotbegin/end
|
||||
|
||||
- support multiple windows: 22-windows
|
||||
- multithreading with multiple commandbuffer
|
||||
|
||||
- compute and drawindirect: 24-nbody (needs compute shaders)
|
||||
@ -382,18 +381,18 @@ namespace bgfx { namespace mtl
|
||||
#define SHADER_FUNCTION_NAME ("xlatMtlMain")
|
||||
#define SHADER_UNIFORM_NAME ("_mtl_u")
|
||||
|
||||
struct RendererContextMtl;
|
||||
static RendererContextMtl* s_renderMtl;
|
||||
|
||||
|
||||
struct RendererContextMtl : public RendererContextI
|
||||
{
|
||||
RendererContextMtl()
|
||||
: m_metalLayer(NULL)
|
||||
, m_backBufferPixelFormatHash(0)
|
||||
, m_maxAnisotropy(1)
|
||||
, m_bufferIndex(0)
|
||||
, m_numWindows(1)
|
||||
: m_bufferIndex(0)
|
||||
, m_numWindows(0)
|
||||
, m_rtMsaa(false)
|
||||
, m_capture(NULL)
|
||||
, m_captureSize(0)
|
||||
, m_drawable(NULL)
|
||||
, m_saveScreenshot(false)
|
||||
{
|
||||
}
|
||||
@ -411,67 +410,21 @@ namespace bgfx { namespace mtl
|
||||
bx::memSet(m_uniforms, 0, sizeof(m_uniforms) );
|
||||
bx::memSet(&m_resolution, 0, sizeof(m_resolution) );
|
||||
|
||||
if (NULL != NSClassFromString(@"MTKView") )
|
||||
m_device = (id<MTLDevice>)g_platformData.context;
|
||||
|
||||
if (NULL == m_device)
|
||||
{
|
||||
MTKView *view = (MTKView *)g_platformData.nwh;
|
||||
if (NULL != view && [view isKindOfClass:NSClassFromString(@"MTKView")])
|
||||
{
|
||||
m_metalLayer = (CAMetalLayer *)view.layer;
|
||||
}
|
||||
m_device = MTLCreateSystemDefaultDevice();
|
||||
}
|
||||
|
||||
if (NULL != NSClassFromString(@"CAMetalLayer") )
|
||||
{
|
||||
if (NULL == m_metalLayer)
|
||||
#if BX_PLATFORM_IOS
|
||||
{
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*)g_platformData.nwh;
|
||||
if (NULL == metalLayer
|
||||
|| ![metalLayer isKindOfClass:NSClassFromString(@"CAMetalLayer")])
|
||||
{
|
||||
BX_WARN(NULL != m_device, "Unable to create Metal device. Please set platform data window to a CAMetalLayer");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_metalLayer = metalLayer;
|
||||
}
|
||||
#elif BX_PLATFORM_OSX
|
||||
{
|
||||
NSObject* nvh = (NSObject*)g_platformData.nwh;
|
||||
if ([nvh isKindOfClass:[CAMetalLayer class]])
|
||||
{
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*)g_platformData.nwh;
|
||||
m_metalLayer = metalLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWindow* nsWindow = (NSWindow*)g_platformData.nwh;
|
||||
[nsWindow.contentView setWantsLayer:YES];
|
||||
m_metalLayer = [CAMetalLayer layer];
|
||||
[nsWindow.contentView setLayer:m_metalLayer];
|
||||
}
|
||||
}
|
||||
#endif // BX_PLATFORM_*
|
||||
|
||||
m_device = (id<MTLDevice>)g_platformData.context;
|
||||
|
||||
if (NULL == m_device)
|
||||
{
|
||||
m_device = MTLCreateSystemDefaultDevice();
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == m_device
|
||||
|| NULL == m_metalLayer)
|
||||
if (NULL == m_device)
|
||||
{
|
||||
BX_WARN(NULL != m_device, "Unable to create Metal device.");
|
||||
return false;
|
||||
}
|
||||
|
||||
retain(m_device);
|
||||
m_metalLayer.device = m_device;
|
||||
m_metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
m_metalLayer.magnificationFilter = kCAFilterNearest;
|
||||
createFrameBuffer(m_fbh, g_platformData.nwh, 0, 0, TextureFormat::Unknown, TextureFormat::UnknownDepth);
|
||||
|
||||
m_cmd.init(m_device);
|
||||
BGFX_FATAL(NULL != m_cmd.m_commandQueue, Fatal::UnableToInitialize, "Unable to create Metal device.");
|
||||
@ -530,7 +483,7 @@ namespace bgfx { namespace mtl
|
||||
release(lib);
|
||||
|
||||
reset(m_renderPipelineDescriptor);
|
||||
m_renderPipelineDescriptor.colorAttachments[0].pixelFormat = m_metalLayer.pixelFormat;
|
||||
m_renderPipelineDescriptor.colorAttachments[0].pixelFormat = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat;
|
||||
m_renderPipelineDescriptor.vertexFunction = m_screenshotBlitProgram.m_vsh->m_function;
|
||||
m_renderPipelineDescriptor.fragmentFunction = m_screenshotBlitProgram.m_fsh->m_function;
|
||||
m_screenshotBlitRenderPipelineState = m_device.newRenderPipelineStateWithDescriptor(m_renderPipelineDescriptor);
|
||||
@ -550,8 +503,8 @@ namespace bgfx { namespace mtl
|
||||
| BGFX_CAPS_OCCLUSION_QUERY
|
||||
| BGFX_CAPS_ALPHA_TO_COVERAGE
|
||||
| BGFX_CAPS_TEXTURE_2D_ARRAY
|
||||
| BGFX_CAPS_SWAP_CHAIN
|
||||
);
|
||||
|
||||
if (BX_ENABLED(BX_PLATFORM_IOS) )
|
||||
{
|
||||
if (iOSVersionEqualOrGreater("9.0.0") )
|
||||
@ -730,8 +683,11 @@ namespace bgfx { namespace mtl
|
||||
MTL_RELEASE(m_textureDescriptor);
|
||||
MTL_RELEASE(m_samplerDescriptor);
|
||||
|
||||
MTL_RELEASE(m_backBufferDepth);
|
||||
MTL_RELEASE(m_backBufferStencil);
|
||||
MTL_RELEASE(m_mainFrameBuffer.m_swapChain->m_backBufferDepth);
|
||||
if (BX_ENABLED(BX_PLATFORM_IOS) )
|
||||
{
|
||||
MTL_RELEASE(m_mainFrameBuffer.m_swapChain->m_backBufferStencil);
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i < MTL_MAX_FRAMES_IN_FLIGHT; ++i)
|
||||
{
|
||||
@ -927,7 +883,15 @@ namespace bgfx { namespace mtl
|
||||
{
|
||||
uint16_t denseIdx = m_numWindows++;
|
||||
m_windows[denseIdx] = _handle;
|
||||
m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat);
|
||||
if (!isValid(_handle))
|
||||
{
|
||||
m_mainFrameBuffer.create(denseIdx, _nwh, _width, _height, _format, _depthFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_frameBuffers[_handle.idx].create(denseIdx, _nwh, _width, _height, _format, _depthFormat);
|
||||
m_frameBuffers[_handle.idx].m_swapChain->resize(m_frameBuffers[_handle.idx], _width, _height, 0);//_resolution.reset);
|
||||
}
|
||||
}
|
||||
|
||||
void destroyFrameBuffer(FrameBufferHandle _handle) override
|
||||
@ -1176,10 +1140,15 @@ namespace bgfx { namespace mtl
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL != m_drawable)
|
||||
for (uint32_t ii = 0, num = m_numWindows; ii < num; ++ii)
|
||||
{
|
||||
m_commandBuffer.presentDrawable(m_drawable);
|
||||
MTL_RELEASE(m_drawable);
|
||||
FrameBufferMtl& frameBuffer = ii == 0 ? m_mainFrameBuffer : m_frameBuffers[m_windows[ii].idx];
|
||||
if (NULL != frameBuffer.m_swapChain &&
|
||||
frameBuffer.m_swapChain->m_drawable)
|
||||
{
|
||||
m_commandBuffer.presentDrawable(frameBuffer.m_swapChain->m_drawable);
|
||||
MTL_RELEASE(frameBuffer.m_swapChain->m_drawable);
|
||||
}
|
||||
}
|
||||
|
||||
m_cmd.kick(true);
|
||||
@ -1188,7 +1157,7 @@ namespace bgfx { namespace mtl
|
||||
|
||||
void updateResolution(const Resolution& _resolution)
|
||||
{
|
||||
m_maxAnisotropy = !!(_resolution.reset & BGFX_RESET_MAXANISOTROPY)
|
||||
m_mainFrameBuffer.m_swapChain->m_maxAnisotropy = !!(_resolution.reset & BGFX_RESET_MAXANISOTROPY)
|
||||
? 16
|
||||
: 1
|
||||
;
|
||||
@ -1203,90 +1172,12 @@ namespace bgfx { namespace mtl
|
||||
|| m_resolution.height != _resolution.height
|
||||
|| (m_resolution.reset&maskFlags) != (_resolution.reset&maskFlags) )
|
||||
{
|
||||
int sampleCount = s_msaa[(_resolution.reset&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT];
|
||||
|
||||
MTLPixelFormat prevMetalLayerPixelFormat = m_metalLayer.pixelFormat;
|
||||
|
||||
#if BX_PLATFORM_OSX > 101300
|
||||
m_metalLayer.displaySyncEnabled = 0 != (_resolution.reset&BGFX_RESET_VSYNC);
|
||||
#endif // BX_PLATFORM_OSX > 101300
|
||||
|
||||
m_metalLayer.drawableSize = CGSizeMake(_resolution.width, _resolution.height);
|
||||
m_metalLayer.pixelFormat = (m_resolution.reset & BGFX_RESET_SRGB_BACKBUFFER)
|
||||
? MTLPixelFormatBGRA8Unorm_sRGB
|
||||
: MTLPixelFormatBGRA8Unorm
|
||||
;
|
||||
MTLPixelFormat prevMetalLayerPixelFormat = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat;
|
||||
|
||||
m_resolution = _resolution;
|
||||
m_resolution.reset &= ~BGFX_RESET_INTERNAL_FORCE;
|
||||
|
||||
m_textureDescriptor.textureType = sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
|
||||
|
||||
if (m_hasPixelFormatDepth32Float_Stencil8)
|
||||
{
|
||||
m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_textureDescriptor.pixelFormat = MTLPixelFormatDepth32Float;
|
||||
}
|
||||
|
||||
m_textureDescriptor.width = _resolution.width;
|
||||
m_textureDescriptor.height = _resolution.height;
|
||||
m_textureDescriptor.depth = 1;
|
||||
m_textureDescriptor.mipmapLevelCount = 1;
|
||||
m_textureDescriptor.sampleCount = sampleCount;
|
||||
m_textureDescriptor.arrayLength = 1;
|
||||
if (m_iOS9Runtime
|
||||
|| m_macOS11Runtime)
|
||||
{
|
||||
m_textureDescriptor.cpuCacheMode = MTLCPUCacheModeDefaultCache;
|
||||
m_textureDescriptor.storageMode = MTLStorageModePrivate;
|
||||
m_textureDescriptor.usage = MTLTextureUsageRenderTarget;
|
||||
}
|
||||
|
||||
if (NULL != m_backBufferDepth)
|
||||
{
|
||||
release(m_backBufferDepth);
|
||||
}
|
||||
|
||||
m_backBufferDepth = m_device.newTextureWithDescriptor(m_textureDescriptor);
|
||||
|
||||
if (NULL != m_backBufferStencil)
|
||||
{
|
||||
release(m_backBufferStencil);
|
||||
}
|
||||
|
||||
if (m_hasPixelFormatDepth32Float_Stencil8)
|
||||
{
|
||||
m_backBufferStencil = m_backBufferDepth;
|
||||
retain(m_backBufferStencil);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_textureDescriptor.pixelFormat = MTLPixelFormatStencil8;
|
||||
m_backBufferStencil = m_device.newTextureWithDescriptor(m_textureDescriptor);
|
||||
}
|
||||
|
||||
if (sampleCount > 1)
|
||||
{
|
||||
if (NULL != m_backBufferColorMSAA)
|
||||
{
|
||||
release(m_backBufferColorMSAA);
|
||||
}
|
||||
|
||||
m_textureDescriptor.pixelFormat = m_metalLayer.pixelFormat;
|
||||
m_backBufferColorMSAA = m_device.newTextureWithDescriptor(m_textureDescriptor);
|
||||
}
|
||||
|
||||
bx::HashMurmur2A murmur;
|
||||
murmur.begin();
|
||||
murmur.add(1);
|
||||
murmur.add( (uint32_t)m_metalLayer.pixelFormat);
|
||||
murmur.add( (uint32_t)m_backBufferDepth.pixelFormat() );
|
||||
murmur.add( (uint32_t)m_backBufferStencil.pixelFormat() );
|
||||
murmur.add( (uint32_t)sampleCount);
|
||||
m_backBufferPixelFormatHash = murmur.end();
|
||||
m_mainFrameBuffer.m_swapChain->resize(m_mainFrameBuffer, _resolution.width, _resolution.height, _resolution.reset);
|
||||
|
||||
for (uint32_t ii = 0; ii < BX_COUNTOF(m_frameBuffers); ++ii)
|
||||
{
|
||||
@ -1298,11 +1189,11 @@ namespace bgfx { namespace mtl
|
||||
m_textVideoMem.resize(false, _resolution.width, _resolution.height);
|
||||
m_textVideoMem.clear();
|
||||
|
||||
if (prevMetalLayerPixelFormat != m_metalLayer.pixelFormat)
|
||||
if (prevMetalLayerPixelFormat != m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat)
|
||||
{
|
||||
MTL_RELEASE(m_screenshotBlitRenderPipelineState)
|
||||
reset(m_renderPipelineDescriptor);
|
||||
m_renderPipelineDescriptor.colorAttachments[0].pixelFormat = m_metalLayer.pixelFormat;
|
||||
m_renderPipelineDescriptor.colorAttachments[0].pixelFormat = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat;
|
||||
m_renderPipelineDescriptor.vertexFunction = m_screenshotBlitProgram.m_vsh->m_function;
|
||||
m_renderPipelineDescriptor.fragmentFunction = m_screenshotBlitProgram.m_fsh->m_function;
|
||||
m_screenshotBlitRenderPipelineState = m_device.newRenderPipelineStateWithDescriptor(m_renderPipelineDescriptor);
|
||||
@ -1647,26 +1538,30 @@ namespace bgfx { namespace mtl
|
||||
|
||||
void setFrameBuffer(RenderPassDescriptor renderPassDescriptor, FrameBufferHandle _fbh, bool _msaa = true)
|
||||
{
|
||||
if (!isValid(_fbh) )
|
||||
if (!isValid(_fbh) || m_frameBuffers[_fbh.idx].m_swapChain)
|
||||
{
|
||||
SwapChainMtl* swapChain =
|
||||
!isValid(_fbh) ?
|
||||
m_mainFrameBuffer.m_swapChain :
|
||||
m_frameBuffers[_fbh.idx].m_swapChain;
|
||||
if (NULL != m_backBufferColorMSAA)
|
||||
{
|
||||
renderPassDescriptor.colorAttachments[0].texture = m_backBufferColorMSAA;
|
||||
renderPassDescriptor.colorAttachments[0].texture = swapChain->m_backBufferColorMSAA;
|
||||
renderPassDescriptor.colorAttachments[0].resolveTexture = NULL != m_screenshotTarget
|
||||
? m_screenshotTarget.m_obj
|
||||
: currentDrawable().texture
|
||||
: swapChain->currentDrawable().texture
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
renderPassDescriptor.colorAttachments[0].texture = NULL != m_screenshotTarget
|
||||
? m_screenshotTarget.m_obj
|
||||
: currentDrawable().texture
|
||||
: swapChain->currentDrawable().texture
|
||||
;
|
||||
}
|
||||
|
||||
renderPassDescriptor.depthAttachment.texture = m_backBufferDepth;
|
||||
renderPassDescriptor.stencilAttachment.texture = m_backBufferStencil;
|
||||
renderPassDescriptor.depthAttachment.texture = swapChain->m_backBufferDepth;
|
||||
renderPassDescriptor.stencilAttachment.texture = swapChain->m_backBufferStencil;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1845,15 +1740,16 @@ namespace bgfx { namespace mtl
|
||||
|
||||
uint32_t frameBufferAttachment = 1;
|
||||
|
||||
if (!isValid(_fbh) )
|
||||
if (!isValid(_fbh) || s_renderMtl->m_frameBuffers[_fbh.idx].m_swapChain)
|
||||
{
|
||||
pd.sampleCount = NULL != m_backBufferColorMSAA
|
||||
? m_backBufferColorMSAA.sampleCount()
|
||||
: 1
|
||||
;
|
||||
pd.colorAttachments[0].pixelFormat = currentDrawable().texture.pixelFormat;
|
||||
pd.depthAttachmentPixelFormat = m_backBufferDepth.m_obj.pixelFormat;
|
||||
pd.stencilAttachmentPixelFormat = m_backBufferStencil.m_obj.pixelFormat;
|
||||
SwapChainMtl* swapChain =
|
||||
!isValid(_fbh) ?
|
||||
s_renderMtl->m_mainFrameBuffer.m_swapChain :
|
||||
s_renderMtl->m_frameBuffers[_fbh.idx].m_swapChain;
|
||||
pd.sampleCount = NULL != swapChain->m_backBufferColorMSAA ? swapChain->m_backBufferColorMSAA.sampleCount() : 1;
|
||||
pd.colorAttachments[0].pixelFormat = swapChain->currentDrawable().texture.pixelFormat;
|
||||
pd.depthAttachmentPixelFormat = swapChain->m_backBufferDepth.m_obj.pixelFormat;
|
||||
pd.stencilAttachmentPixelFormat = swapChain->m_backBufferStencil.m_obj.pixelFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2195,7 +2091,7 @@ namespace bgfx { namespace mtl
|
||||
m_samplerDescriptor.lodMinClamp = 0;
|
||||
m_samplerDescriptor.lodMaxClamp = FLT_MAX;
|
||||
m_samplerDescriptor.normalizedCoordinates = TRUE;
|
||||
m_samplerDescriptor.maxAnisotropy = (0 != (_flags & (BGFX_SAMPLER_MIN_ANISOTROPIC|BGFX_SAMPLER_MAG_ANISOTROPIC) ) ) ? m_maxAnisotropy : 1;
|
||||
m_samplerDescriptor.maxAnisotropy = (0 != (_flags & (BGFX_SAMPLER_MIN_ANISOTROPIC|BGFX_SAMPLER_MAG_ANISOTROPIC) ) ) ? m_mainFrameBuffer.m_swapChain->m_maxAnisotropy : 1;
|
||||
|
||||
if (m_macOS11Runtime
|
||||
|| [m_device supportsFeatureSet:(MTLFeatureSet)4 /*MTLFeatureSet_iOS_GPUFamily3_v1*/])
|
||||
@ -2277,6 +2173,7 @@ namespace bgfx { namespace mtl
|
||||
ShaderMtl m_shaders[BGFX_CONFIG_MAX_SHADERS];
|
||||
ProgramMtl m_program[BGFX_CONFIG_MAX_PROGRAMS];
|
||||
TextureMtl m_textures[BGFX_CONFIG_MAX_TEXTURES];
|
||||
FrameBufferMtl m_mainFrameBuffer;
|
||||
FrameBufferMtl m_frameBuffers[BGFX_CONFIG_MAX_FRAME_BUFFERS];
|
||||
VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS];
|
||||
UniformRegistry m_uniformReg;
|
||||
@ -2320,8 +2217,6 @@ namespace bgfx { namespace mtl
|
||||
FrameBufferHandle m_renderCommandEncoderFrameBufferHandle;
|
||||
};
|
||||
|
||||
static RendererContextMtl* s_renderMtl;
|
||||
|
||||
RendererContextI* rendererCreate(const Init& _init)
|
||||
{
|
||||
s_renderMtl = BX_NEW(g_allocator, RendererContextMtl);
|
||||
@ -2903,8 +2798,163 @@ namespace bgfx { namespace mtl
|
||||
}
|
||||
}
|
||||
|
||||
SwapChainMtl::~SwapChainMtl()
|
||||
{
|
||||
MTL_RELEASE(m_backBufferDepth);
|
||||
if (BX_ENABLED(BX_PLATFORM_IOS) )
|
||||
{
|
||||
MTL_RELEASE(m_backBufferStencil);
|
||||
}
|
||||
}
|
||||
|
||||
void SwapChainMtl::init(void* _nwh)
|
||||
{
|
||||
if (NULL != NSClassFromString(@"MTKView") )
|
||||
{
|
||||
MTKView *view = (MTKView *)_nwh;
|
||||
if (NULL != view && [view isKindOfClass:NSClassFromString(@"MTKView")])
|
||||
{
|
||||
m_metalLayer = (CAMetalLayer *)view.layer;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != NSClassFromString(@"CAMetalLayer") )
|
||||
{
|
||||
if (NULL == m_metalLayer)
|
||||
#if BX_PLATFORM_IOS
|
||||
{
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*)_nwh;
|
||||
if (NULL == metalLayer
|
||||
|| ![metalLayer isKindOfClass:NSClassFromString(@"CAMetalLayer")])
|
||||
{
|
||||
BX_WARN(NULL != metalLayer, "Unable to create Metal device. Please set platform data window to a CAMetalLayer");
|
||||
return;
|
||||
}
|
||||
|
||||
m_metalLayer = metalLayer;
|
||||
}
|
||||
#elif BX_PLATFORM_OSX
|
||||
{
|
||||
NSObject* nvh = (NSObject*)_nwh;
|
||||
if ([nvh isKindOfClass:[CAMetalLayer class]])
|
||||
{
|
||||
CAMetalLayer* metalLayer = (CAMetalLayer*)_nwh;
|
||||
m_metalLayer = metalLayer;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSWindow* nsWindow = (NSWindow*)_nwh;
|
||||
[nsWindow.contentView setWantsLayer:YES];
|
||||
m_metalLayer = [CAMetalLayer layer];
|
||||
[nsWindow.contentView setLayer:m_metalLayer];
|
||||
}
|
||||
}
|
||||
#endif // BX_PLATFORM_*
|
||||
}
|
||||
|
||||
if (NULL == m_metalLayer)
|
||||
{
|
||||
BX_WARN(NULL != s_renderMtl->m_device, "Unable to create Metal device.");
|
||||
return;
|
||||
}
|
||||
|
||||
m_metalLayer.device = s_renderMtl->m_device;
|
||||
m_metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
|
||||
m_metalLayer.magnificationFilter = kCAFilterNearest;
|
||||
}
|
||||
|
||||
void SwapChainMtl::resize(FrameBufferMtl &_frameBuffer, uint32_t _width, uint32_t _height, uint32_t _flags)
|
||||
{
|
||||
int sampleCount = s_msaa[(_flags&BGFX_RESET_MSAA_MASK)>>BGFX_RESET_MSAA_SHIFT];
|
||||
|
||||
#if BX_PLATFORM_OSX > 101300
|
||||
m_metalLayer.displaySyncEnabled = 0 != (_flags&BGFX_RESET_VSYNC);
|
||||
#endif // BX_PLATFORM_OSX > 101300
|
||||
|
||||
m_metalLayer.drawableSize = CGSizeMake(_width, _height);
|
||||
m_metalLayer.pixelFormat = (_flags & BGFX_RESET_SRGB_BACKBUFFER)
|
||||
? MTLPixelFormatBGRA8Unorm_sRGB
|
||||
: MTLPixelFormatBGRA8Unorm
|
||||
;
|
||||
|
||||
TextureDescriptor desc = s_renderMtl->m_textureDescriptor;
|
||||
|
||||
desc.textureType = sampleCount > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
|
||||
|
||||
if (s_renderMtl->m_hasPixelFormatDepth32Float_Stencil8)
|
||||
desc.pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
else
|
||||
desc.pixelFormat = MTLPixelFormatDepth32Float;
|
||||
|
||||
desc.width = _width;
|
||||
desc.height = _height;
|
||||
desc.depth = 1;
|
||||
desc.mipmapLevelCount = 1;
|
||||
desc.sampleCount = sampleCount;
|
||||
desc.arrayLength = 1;
|
||||
if ( s_renderMtl->m_iOS9Runtime || s_renderMtl->m_macOS11Runtime )
|
||||
{
|
||||
desc.cpuCacheMode = MTLCPUCacheModeDefaultCache;
|
||||
desc.storageMode = MTLStorageModePrivate;
|
||||
desc.usage = MTLTextureUsageRenderTarget;
|
||||
}
|
||||
|
||||
if (NULL != m_backBufferDepth)
|
||||
{
|
||||
release(m_backBufferDepth);
|
||||
}
|
||||
m_backBufferDepth = s_renderMtl->m_device.newTextureWithDescriptor(desc);
|
||||
|
||||
if (NULL != m_backBufferStencil)
|
||||
{
|
||||
release(m_backBufferStencil);
|
||||
}
|
||||
|
||||
if (s_renderMtl->m_hasPixelFormatDepth32Float_Stencil8)
|
||||
{
|
||||
m_backBufferStencil = m_backBufferDepth;
|
||||
retain(m_backBufferStencil);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.pixelFormat = MTLPixelFormatStencil8;
|
||||
m_backBufferStencil = s_renderMtl->m_device.newTextureWithDescriptor(desc);
|
||||
}
|
||||
|
||||
if ( sampleCount > 1 )
|
||||
{
|
||||
if (NULL != m_backBufferColorMSAA)
|
||||
{
|
||||
release(m_backBufferColorMSAA);
|
||||
}
|
||||
desc.pixelFormat = m_metalLayer.pixelFormat;
|
||||
m_backBufferColorMSAA = s_renderMtl->m_device.newTextureWithDescriptor(desc);
|
||||
}
|
||||
|
||||
bx::HashMurmur2A murmur;
|
||||
murmur.begin();
|
||||
murmur.add(1);
|
||||
murmur.add((uint32_t)m_metalLayer.pixelFormat);
|
||||
murmur.add((uint32_t)m_backBufferDepth.pixelFormat());
|
||||
murmur.add((uint32_t)m_backBufferStencil.pixelFormat());
|
||||
murmur.add((uint32_t)sampleCount);
|
||||
_frameBuffer.m_pixelFormatHash = murmur.end();
|
||||
}
|
||||
|
||||
id<CAMetalDrawable> SwapChainMtl::currentDrawable()
|
||||
{
|
||||
if (m_drawable == nil)
|
||||
{
|
||||
m_drawable = m_metalLayer.nextDrawable;
|
||||
retain(m_drawable); // keep alive to be useable at 'flip'
|
||||
}
|
||||
|
||||
return m_drawable;
|
||||
}
|
||||
|
||||
void FrameBufferMtl::create(uint8_t _num, const Attachment* _attachment)
|
||||
{
|
||||
m_swapChain = NULL;
|
||||
m_denseIdx = UINT16_MAX;
|
||||
m_num = 0;
|
||||
m_width = 0;
|
||||
@ -2968,7 +3018,13 @@ namespace bgfx { namespace mtl
|
||||
|
||||
void FrameBufferMtl::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _format, TextureFormat::Enum _depthFormat)
|
||||
{
|
||||
BX_UNUSED(_denseIdx, _nwh, _width, _height, _format, _depthFormat);
|
||||
BX_UNUSED(_format, _depthFormat);
|
||||
m_swapChain = BX_NEW(g_allocator, SwapChainMtl);
|
||||
m_width = _width;
|
||||
m_height = _height;
|
||||
m_denseIdx = _denseIdx;
|
||||
|
||||
m_swapChain->init(_nwh);
|
||||
}
|
||||
|
||||
void FrameBufferMtl::postReset()
|
||||
@ -2977,6 +3033,12 @@ namespace bgfx { namespace mtl
|
||||
|
||||
uint16_t FrameBufferMtl::destroy()
|
||||
{
|
||||
if (NULL != m_swapChain)
|
||||
{
|
||||
BX_DELETE(g_allocator, m_swapChain);
|
||||
m_swapChain = NULL;
|
||||
}
|
||||
|
||||
m_num = 0;
|
||||
m_depthHandle.idx = kInvalidHandle;
|
||||
|
||||
@ -3307,7 +3369,7 @@ namespace bgfx { namespace mtl
|
||||
if (NULL == m_screenshotTarget)
|
||||
{
|
||||
m_textureDescriptor.textureType = MTLTextureType2D;
|
||||
m_textureDescriptor.pixelFormat = m_metalLayer.pixelFormat;
|
||||
m_textureDescriptor.pixelFormat = m_mainFrameBuffer.m_swapChain->m_metalLayer.pixelFormat;
|
||||
m_textureDescriptor.width = m_resolution.width;
|
||||
m_textureDescriptor.height = m_resolution.height;
|
||||
m_textureDescriptor.depth = 1;
|
||||
@ -3556,7 +3618,7 @@ namespace bgfx { namespace mtl
|
||||
? MTLLoadActionClear
|
||||
: MTLLoadActionLoad
|
||||
;
|
||||
depthAttachment.storeAction = NULL != m_backBufferColorMSAA
|
||||
depthAttachment.storeAction = NULL != m_mainFrameBuffer.m_swapChain->m_backBufferColorMSAA
|
||||
? MTLStoreActionDontCare
|
||||
: MTLStoreActionStore
|
||||
;
|
||||
@ -3570,7 +3632,7 @@ namespace bgfx { namespace mtl
|
||||
? MTLLoadActionClear
|
||||
: MTLLoadActionLoad
|
||||
;
|
||||
stencilAttachment.storeAction = NULL != m_backBufferColorMSAA
|
||||
stencilAttachment.storeAction = NULL != m_mainFrameBuffer.m_swapChain->m_backBufferColorMSAA
|
||||
? MTLStoreActionDontCare
|
||||
: MTLStoreActionStore
|
||||
;
|
||||
@ -4212,7 +4274,7 @@ namespace bgfx { namespace mtl
|
||||
if (m_screenshotTarget)
|
||||
{
|
||||
RenderPassDescriptor renderPassDescriptor = newRenderPassDescriptor();
|
||||
renderPassDescriptor.colorAttachments[0].texture = currentDrawable().texture;
|
||||
renderPassDescriptor.colorAttachments[0].texture = m_mainFrameBuffer.m_swapChain->currentDrawable().texture;
|
||||
renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
|
||||
|
||||
rce = m_commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor);
|
||||
|
Loading…
Reference in New Issue
Block a user