Selaa lähdekoodia

ImDrawCallback_ResetRenderState: Added Metal.

Max Thrun 6 vuotta sitten
vanhempi
commit
7c6ba3a1da
2 muutettua tiedostoa jossa 43 lisäystä ja 21 poistoa
  1. 3 3
      docs/CHANGELOG.txt
  2. 40 18
      examples/imgui_impl_metal.mm

+ 3 - 3
docs/CHANGELOG.txt

@@ -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)

+ 40 - 18
examples/imgui_impl_metal.mm

@@ -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
-         commandBuffer:(id<MTLCommandBuffer>)commandBuffer
-        commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
+- (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,8 +489,12 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
-                // User callback (registered via ImDrawList::AddCallback)
-                pcmd->UserCallback(cmd_list, pcmd);
+                // 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
             {