ImDrawCallback_ResetRenderState: Added Metal.

This commit is contained in:
Max Thrun 2019-03-29 11:11:55 -07:00 committed by omar
parent 5c1cd5c8c7
commit 7c6ba3a1da
2 changed files with 43 additions and 21 deletions

View File

@ -47,9 +47,9 @@ Breaking Changes:
Other Changes:
- ImDrawList: Added ImDrawCallback_ResetRenderState, a special ImDrawList::AddCallback() value
to request the renderer back-end to reset its render state. (#2037, #1639, #2452)
- Examples: Added support for ImDrawCallback_ResetRenderState in all renderer back-ends.
Each renderer code setting up initial render state has been moved to a function so it could
be called at the start of rendering and when a ResetRenderState is requested. (#2037, #1639, #2452)
Examples: Added support for ImDrawCallback_ResetRenderState in all renderer back-ends. Each
renderer code setting up initial render state has been moved to a function so it could be
called at the start of rendering and when a ResetRenderState is requested. [@ocornut, @bear24rw]
- InputText: Fixed selection background starts rendering one frame after the cursor movement
when first transitioning from no-selection to has-selection. (Bug in 1.69) (#2436) [@Nazg-Gul]
- InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336)

View File

@ -56,6 +56,12 @@
- (void)enqueueReusableBuffer:(MetalBuffer *)buffer;
- (id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device;
- (void)emptyRenderPipelineStateCache;
- (void)setupRenderState:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
vertexBuffer:(MetalBuffer *)vertexBuffer
vertexBufferOffset:(size_t)vertexBufferOffset;
- (void)renderDrawData:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
@ -397,16 +403,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
[self.renderPipelineStateCache removeAllObjects];
}
- (void)renderDrawData:(ImDrawData *)drawData
- (void)setupRenderState:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
vertexBuffer:(MetalBuffer *)vertexBuffer
vertexBufferOffset:(size_t)vertexBufferOffset
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x);
int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
return;
[commandEncoder setCullMode:MTLCullModeNone];
[commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState];
@ -417,12 +420,13 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
{
.originX = 0.0,
.originY = 0.0,
.width = double(fb_width),
.height = double(fb_height),
.width = (double)(drawData->DisplaySize.x * drawData->FramebufferScale.x),
.height = (double)(drawData->DisplaySize.y * drawData->FramebufferScale.y),
.znear = 0.0,
.zfar = 1.0
};
[commandEncoder setViewport:viewport];
float L = drawData->DisplayPos.x;
float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
float T = drawData->DisplayPos.y;
@ -436,18 +440,32 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
{ 0.0f, 0.0f, 1/(F-N), 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
};
[commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
[commandEncoder setRenderPipelineState:renderPipelineState];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
[commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
}
- (void)renderDrawData:(ImDrawData *)drawData
commandBuffer:(id<MTLCommandBuffer>)commandBuffer
commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x);
int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y);
if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
return;
id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
size_t vertexBufferLength = drawData->TotalVtxCount * sizeof(ImDrawVert);
size_t indexBufferLength = drawData->TotalIdxCount * sizeof(ImDrawIdx);
MetalBuffer* vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
MetalBuffer* indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
[commandEncoder setRenderPipelineState:renderPipelineState];
[commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:0];
// Will project scissor/clipping rectangles into framebuffer space
ImVec2 clip_off = drawData->DisplayPos; // (0,0) unless using multi-viewports
@ -471,7 +489,11 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback)
{
// User callback (registered via ImDrawList::AddCallback)
// User callback, registered via ImDrawList::AddCallback()
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
[self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:vertexBufferOffset];
else
pcmd->UserCallback(cmd_list, pcmd);
}
else