Examples: Comments + shallow coding convention tweak to be consistent across examples and with imgui_impl_osx

This commit is contained in:
omar 2018-07-08 11:16:11 +02:00
parent 569e0f07f1
commit 89e2ddf07f
3 changed files with 67 additions and 38 deletions

View File

@ -166,12 +166,12 @@ example_win32_directx12/
example_apple_metal/
OSX & iOS + Metal.
It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
Note that instead of the OSX bindings, you may want to use GLFW or SDL which will also support Windows, Linux along with OSX.
(NB: you may still want to use GLFW or SDL which will also support Windows, Linux along with OSX.)
= game template + imgui_impl_osx.mm + imgui_impl_metal.mm
example_apple_opengl2/
OSX + OpenGL2.
Note that instead of the OSX bindings, you may want to use GLFW or SDL which will also support Windows, Linux along with OSX.
(NB: you may still want to use GLFW or SDL which will also support Windows, Linux along with OSX.)
= main.mm + imgui_impl_osx.mm + imgui_impl_opengl2.cpp
example_glfw_opengl2/

View File

@ -2,5 +2,7 @@
## Introduction
This example shows how to render ImGui with Metal. It is based on the cross-platform game template provided with Xcode as of Xcode 9.
This example shows how to integrate Dear ImGui with Metal. It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
(NB: you may still want to use GLFW or SDL which will also support Windows, Linux along with OSX.)

View File

@ -128,8 +128,10 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
#pragma mark - MetalBuffer implementation
@implementation MetalBuffer
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer {
if ((self = [super init])) {
- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer
{
if ((self = [super init]))
{
_buffer = buffer;
_lastReuseTime = [NSDate date].timeIntervalSince1970;
}
@ -140,8 +142,10 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
#pragma mark - FramebufferDescriptor implementation
@implementation FramebufferDescriptor
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor {
if ((self = [super init])) {
- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor
{
if ((self = [super init]))
{
_sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
_colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
_depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
@ -150,7 +154,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
return self;
}
- (nonnull id)copyWithZone:(nullable NSZone *)zone {
- (nonnull id)copyWithZone:(nullable NSZone *)zone
{
FramebufferDescriptor *copy = [[FramebufferDescriptor allocWithZone:zone] init];
copy.sampleCount = self.sampleCount;
copy.colorPixelFormat = self.colorPixelFormat;
@ -159,7 +164,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
return copy;
}
- (NSUInteger)hash {
- (NSUInteger)hash
{
NSUInteger sc = _sampleCount & 0x3;
NSUInteger cf = _colorPixelFormat & 0x3FF;
NSUInteger df = _depthPixelFormat & 0x3FF;
@ -168,12 +174,12 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
return hash;
}
- (BOOL)isEqual:(id)object {
- (BOOL)isEqual:(id)object
{
FramebufferDescriptor *other = object;
if (![other isKindOfClass:[FramebufferDescriptor class]]) {
if (![other isKindOfClass:[FramebufferDescriptor class]])
return NO;
}
return other.sampleCount == self.sampleCount &&
return other.sampleCount == self.sampleCount &&
other.colorPixelFormat == self.colorPixelFormat &&
other.depthPixelFormat == self.depthPixelFormat &&
other.stencilPixelFormat == self.stencilPixelFormat;
@ -185,7 +191,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
@implementation MetalContext
- (instancetype)init {
if ((self = [super init])) {
if ((self = [super init]))
{
_renderPipelineStateCache = [NSMutableDictionary dictionary];
_bufferCache = [NSMutableArray array];
_lastBufferCachePurge = [NSDate date].timeIntervalSince1970;
@ -193,14 +200,20 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
return self;
}
- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device {
- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device
{
MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
depthStencilDescriptor.depthWriteEnabled = NO;
depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
self.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
}
- (void)makeFontTextureWithDevice:(id<MTLDevice>)device {
// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
// You can make that change in your implementation.
- (void)makeFontTextureWithDevice:(id<MTLDevice>)device
{
ImGuiIO &io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
@ -220,14 +233,18 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
self.fontTexture = texture;
}
- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device {
- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
{
NSTimeInterval now = [NSDate date].timeIntervalSince1970;
// Purge old buffers that haven't been useful for a while
if (now - self.lastBufferCachePurge > 1.0) {
if (now - self.lastBufferCachePurge > 1.0)
{
NSMutableArray *survivors = [NSMutableArray array];
for (MetalBuffer *candidate in self.bufferCache) {
if (candidate.lastReuseTime > self.lastBufferCachePurge) {
for (MetalBuffer *candidate in self.bufferCache)
{
if (candidate.lastReuseTime > self.lastBufferCachePurge)
{
[survivors addObject:candidate];
}
}
@ -237,13 +254,12 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
// See if we have a buffer we can reuse
MetalBuffer *bestCandidate = nil;
for (MetalBuffer *candidate in self.bufferCache) {
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime)) {
for (MetalBuffer *candidate in self.bufferCache)
if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
bestCandidate = candidate;
}
}
if (bestCandidate != nil) {
if (bestCandidate != nil)
{
[self.bufferCache removeObject:bestCandidate];
bestCandidate.lastReuseTime = now;
return bestCandidate;
@ -254,16 +270,19 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
return [[MetalBuffer alloc] initWithBuffer:backing];
}
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer {
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer
{
[self.bufferCache addObject:buffer];
}
- (_Nullable id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device {
- (_Nullable id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device
{
// Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
// Thie hit rate for this cache should be very near 100%.
id<MTLRenderPipelineState> renderPipelineState = self.renderPipelineStateCache[self.framebufferDescriptor];
if (renderPipelineState == nil) {
if (renderPipelineState == nil)
{
// No luck; make a new render pipeline state
renderPipelineState = [self _renderPipelineStateForFramebufferDescriptor:self.framebufferDescriptor device:device];
// Cache render pipeline state for later reuse
@ -314,7 +333,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
"}\n";
id<MTLLibrary> library = [device newLibraryWithSource:shaderSource options:nil error:&error];
if (library == nil) {
if (library == nil)
{
NSLog(@"Error: failed to create Metal library: %@", error);
return nil;
}
@ -322,7 +342,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
id<MTLFunction> vertexFunction = [library newFunctionWithName:@"vertex_main"];
id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"fragment_main"];
if (vertexFunction == nil || fragmentFunction == nil) {
if (vertexFunction == nil || fragmentFunction == nil)
{
NSLog(@"Error: failed to find Metal shader functions in library: %@", error);
return nil;
}
@ -358,14 +379,16 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;
id<MTLRenderPipelineState> renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
if (error != nil) {
if (error != nil)
{
NSLog(@"Error: failed to create Metal pipeline state: %@", error);
}
return renderPipelineState;
}
- (void)emptyRenderPipelineStateCache {
- (void)emptyRenderPipelineStateCache
{
[self.renderPipelineStateCache removeAllObjects];
}
@ -387,12 +410,15 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
// Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPps (top left) to
// draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
MTLViewport viewport = { .originX = 0.0,
MTLViewport viewport =
{
.originX = 0.0,
.originY = 0.0,
.width = double(fb_width),
.height = double(fb_height),
.znear = 0.0,
.zfar = 1.0 };
.zfar = 1.0
};
[commandEncoder setViewport:viewport];
float L = drawData->DisplayPos.x;
float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
@ -412,7 +438,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
size_t vertexBufferLength = 0;
size_t indexBufferLength = 0;
for (int n = 0; n < drawData->CmdListsCount; n++) {
for (int n = 0; n < drawData->CmdListsCount; n++)
{
const ImDrawList* cmd_list = drawData->CmdLists[n];
vertexBufferLength += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
indexBufferLength += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
@ -461,9 +488,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
// Bind texture, Draw
if (pcmd->TextureId != NULL) {
if (pcmd->TextureId != NULL)
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(pcmd->TextureId) atIndex:0];
}
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:pcmd->ElemCount
indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
@ -479,7 +505,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
}
__weak id weakSelf = self;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>) {
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf enqueueReusableBuffer:vertexBuffer];
[weakSelf enqueueReusableBuffer:indexBuffer];