Sources/N-body/MetalNBodyPresenter.mm
/* |
Copyright (C) 2015-2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Utility class for rendering (encoding into Metal pipeline components of) N-Body simulation and presenting the frame |
*/ |
#import "NBodyDefaults.h" |
#import "NBodyPreferences.h" |
#import "MetalNBodyComputeStage.h" |
#import "MetalNBodyRenderStage.h" |
#import "MetalNBodyPresenter.h" |
@implementation MetalNBodyPresenter |
{ |
@private |
BOOL _haveEncoder; |
BOOL _isEncoded; |
NSDictionary* _globals; |
NSDictionary* _parameters; |
id<MTLLibrary> m_Library; |
id<MTLCommandBuffer> m_CmdBuffer; |
id<MTLCommandQueue> m_CmdQueue; |
MetalNBodyRenderStage* mpRender; |
MetalNBodyComputeStage* mpCompute; |
} |
- (instancetype) init |
{ |
self = [super init]; |
if(self) |
{ |
_haveEncoder = NO; |
_isEncoded = NO; |
_globals = nil; |
_parameters = nil; |
m_CmdBuffer = nil; |
m_CmdQueue = nil; |
m_Library = nil; |
mpRender = nil; |
mpCompute = nil; |
} // if |
return self; |
} // init |
// N-body simulation global parameters |
- (void) setGlobals:(NSDictionary *)globals |
{ |
_globals = globals; |
if(mpRender) |
{ |
mpRender.globals = _globals; |
} // if |
} // setParameters |
// N-body parameters for simulation types |
- (void) setParameters:(NSDictionary *)parameters |
{ |
_parameters = parameters; |
if(mpRender) |
{ |
mpRender.parameters = _parameters; |
} // if |
} // setParameters |
// Aspect ratio |
- (void) setAspect:(float)aspect |
{ |
if(mpRender) |
{ |
mpRender.aspect = aspect; |
} // if |
} // setAspect |
// Orthographic projection configuration type |
- (void) setConfig:(uint32_t)config |
{ |
if(mpRender) |
{ |
mpRender.config = config; |
} // if |
} // setConfig |
// Update the linear transformation mvp matrix |
- (void) setUpdate:(BOOL)update |
{ |
if(mpRender) |
{ |
mpRender.update = update; |
} // if |
} // setUpdate |
// Color host pointer |
- (nullable simd::float4 *) colors |
{ |
simd::float4* pColors = nullptr; |
if(mpRender) |
{ |
pColors = mpRender.colors; |
} // if |
return pColors; |
} // colors |
// Position host pointer |
- (nullable simd::float4 *) position |
{ |
simd::float4* pPosition = nullptr; |
if(mpCompute) |
{ |
pPosition = mpCompute.position; |
} // if |
return pPosition; |
} // position |
// Velocity host pointer |
- (nullable simd::float4 *) velocity |
{ |
simd::float4* pVelocity = nullptr; |
if(mpCompute) |
{ |
pVelocity = mpCompute.velocity; |
} // if |
return pVelocity; |
} // velocity |
- (BOOL) _acquire:(nullable id<MTLDevice>)device |
{ |
if(device) |
{ |
m_Library = [device newDefaultLibrary]; |
if(!m_Library) |
{ |
NSLog(@">> ERROR: Failed to instantiate a new default m_Library!"); |
return NO; |
} // if |
m_CmdQueue = [device newCommandQueue]; |
if(!m_CmdQueue) |
{ |
NSLog(@">> ERROR: Failed to instantiate a new command queue!"); |
return NO; |
} // if |
mpCompute = [MetalNBodyComputeStage new]; |
if(!mpCompute) |
{ |
NSLog(@">> ERROR: Failed to instantiate a N-Body compute object!"); |
return NO; |
} // if |
mpCompute.globals = _globals; |
mpCompute.library = m_Library; |
mpCompute.device = device; |
if(!mpCompute.isStaged) |
{ |
NSLog(@">> ERROR: Failed to acquire a N-Body compute resources!"); |
return NO; |
} // if |
mpRender = [MetalNBodyRenderStage new]; |
if(!mpRender) |
{ |
NSLog(@">> ERROR: Failed to instantiate a N-Body render stage object!"); |
return NO; |
} // if |
mpRender.globals = _globals; |
mpRender.library = m_Library; |
mpRender.device = device; |
if(!mpRender.isStaged) |
{ |
NSLog(@">> ERROR: Failed to acquire a N-Body render stage resources!"); |
return NO; |
} // if |
return YES; |
} // if |
else |
{ |
NSLog(@">> ERROR: Metal device is nil!"); |
} // if |
return NO; |
} // acquire |
// Generate all the resources (including fragment, vertex and compute stages) |
// for rendering N-Body simulation |
- (void) acquire:(nullable id<MTLDevice>)device |
{ |
if(!_haveEncoder) |
{ |
_haveEncoder = [self _acquire:device]; |
} // if |
} // acquire |
- (BOOL) _encode:(nullable id<CAMetalDrawable>)drawable |
{ |
m_CmdBuffer = [m_CmdQueue commandBuffer]; |
if(!m_CmdBuffer) |
{ |
NSLog(@">> ERROR: Failed to acquire a command buffer!"); |
return NO; |
} // if |
mpCompute.parameters = _parameters; |
mpCompute.cmdBuffer = m_CmdBuffer; |
mpRender.positions = mpCompute.buffer; |
mpRender.cmdBuffer = m_CmdBuffer; |
mpRender.drawable = drawable; |
[m_CmdBuffer presentDrawable:drawable]; |
[m_CmdBuffer commit]; |
[mpCompute swapBuffers]; |
return YES; |
} // _encode |
// Encode vertex, fragment, and compute stages, then present the drawable |
- (void) encode:(nullable id<CAMetalDrawable>)drawable |
{ |
_isEncoded = [self _encode:drawable]; |
} // encode |
// Wait until the render encoding is complete |
- (void) finish |
{ |
if(m_CmdBuffer) |
{ |
[m_CmdBuffer waitUntilCompleted]; |
} // if |
} // finish |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-12-10