summaryrefslogtreecommitdiffstats
path: root/Imgui/src/ImGuiDiligentRenderer.cpp
diff options
context:
space:
mode:
authorThomas Tissot <thomas.tissot@zen.ly>2020-06-08 08:53:59 +0000
committerThomas Tissot <thomas.tissot@zen.ly>2020-06-12 13:27:51 +0000
commitcfdba551859bf3d5506979e5cf9a0c1ed6cd75b8 (patch)
tree3a7908813a7578cfc41bc64684d37624f5cae8ab /Imgui/src/ImGuiDiligentRenderer.cpp
parentMerge pull request #10 from dolphineye/user/dolphineye/imgui-framebuffer-scale (diff)
downloadDiligentTools-cfdba551859bf3d5506979e5cf9a0c1ed6cd75b8.tar.gz
DiligentTools-cfdba551859bf3d5506979e5cf9a0c1ed6cd75b8.zip
Moved ImGuiImplDiligent_Internal into separate compilation unit
Diffstat (limited to 'Imgui/src/ImGuiDiligentRenderer.cpp')
-rw-r--r--Imgui/src/ImGuiDiligentRenderer.cpp575
1 files changed, 575 insertions, 0 deletions
diff --git a/Imgui/src/ImGuiDiligentRenderer.cpp b/Imgui/src/ImGuiDiligentRenderer.cpp
new file mode 100644
index 0000000..780e5a2
--- /dev/null
+++ b/Imgui/src/ImGuiDiligentRenderer.cpp
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include <cstddef>
+#include "ImGuiDiligentRenderer.hpp"
+#include "RenderDevice.h"
+#include "DeviceContext.h"
+#include "MapHelper.hpp"
+
+namespace Diligent
+{
+
+static const char* VertexShaderSource = R"(
+cbuffer Constants
+{
+ float4x4 ProjectionMatrix;
+}
+
+struct VSInput
+{
+ float2 pos : ATTRIB0;
+ float2 uv : ATTRIB1;
+ float4 col : ATTRIB2;
+};
+
+struct PSInput
+{
+ float4 pos : SV_POSITION;
+ float4 col : COLOR;
+ float2 uv : TEXCOORD;
+};
+
+void main(in VSInput VSIn, out PSInput PSIn)
+{
+ PSIn.pos = mul(ProjectionMatrix, float4(VSIn.pos.xy, 0.0, 1.0));
+ PSIn.col = VSIn.col;
+ PSIn.uv = VSIn.uv;
+}
+)";
+
+static const char* PixelShaderSource = R"(
+struct PSInput
+{
+ float4 pos : SV_POSITION;
+ float4 col : COLOR;
+ float2 uv : TEXCOORD;
+};
+
+Texture2D Texture;
+SamplerState Texture_sampler;
+
+float4 main(in PSInput PSIn) : SV_Target
+{
+ return PSIn.col * Texture.Sample(Texture_sampler, PSIn.uv);
+}
+)";
+
+ImGuiDiligentRenderer::ImGuiDiligentRenderer(IRenderDevice* pDevice,
+ TEXTURE_FORMAT BackBufferFmt,
+ TEXTURE_FORMAT DepthBufferFmt,
+ Uint32 InitialVertexBufferSize,
+ Uint32 InitialIndexBufferSize) :
+ // clang-format off
+ m_pDevice {pDevice},
+ m_BackBufferFmt {BackBufferFmt},
+ m_DepthBufferFmt {DepthBufferFmt},
+ m_VertexBufferSize{InitialVertexBufferSize},
+ m_IndexBufferSize {InitialIndexBufferSize}
+// clang-format on
+{
+ // Setup back-end capabilities flags
+ IMGUI_CHECKVERSION();
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendRendererName = "ImGuiDiligentRenderer";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ CreateDeviceObjects();
+}
+
+ImGuiDiligentRenderer::~ImGuiDiligentRenderer()
+{
+}
+
+void ImGuiDiligentRenderer::NewFrame(Uint32 RenderSurfaceWidth,
+ Uint32 RenderSurfaceHeight,
+ SURFACE_TRANSFORM SurfacePreTransform)
+{
+ if (!m_pPSO)
+ CreateDeviceObjects();
+ m_RenderSurfaceWidth = RenderSurfaceWidth;
+ m_RenderSurfaceHeight = RenderSurfaceHeight;
+ m_SurfacePreTransform = SurfacePreTransform;
+}
+
+void ImGuiDiligentRenderer::EndFrame()
+{
+}
+
+void ImGuiDiligentRenderer::InvalidateDeviceObjects()
+{
+ m_pVB.Release();
+ m_pIB.Release();
+ m_pVertexConstantBuffer.Release();
+ m_pPSO.Release();
+ m_pFontSRV.Release();
+ m_pSRB.Release();
+}
+
+void ImGuiDiligentRenderer::CreateDeviceObjects()
+{
+ InvalidateDeviceObjects();
+
+ ShaderCreateInfo ShaderCI;
+ ShaderCI.UseCombinedTextureSamplers = true;
+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
+
+ RefCntAutoPtr<IShader> pVS;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_VERTEX;
+ ShaderCI.Desc.Name = "Imgui VS";
+ ShaderCI.Source = VertexShaderSource;
+ m_pDevice->CreateShader(ShaderCI, &pVS);
+ }
+
+ RefCntAutoPtr<IShader> pPS;
+ {
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ ShaderCI.Desc.Name = "Imgui PS";
+ ShaderCI.Source = PixelShaderSource;
+ m_pDevice->CreateShader(ShaderCI, &pPS);
+ }
+
+ PipelineStateCreateInfo PSOCreateInfo;
+ PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
+
+ PSODesc.Name = "ImGUI PSO";
+ auto& GraphicsPipeline = PSODesc.GraphicsPipeline;
+
+ GraphicsPipeline.NumRenderTargets = 1;
+ GraphicsPipeline.RTVFormats[0] = m_BackBufferFmt;
+ GraphicsPipeline.DSVFormat = m_DepthBufferFmt;
+ GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+
+ GraphicsPipeline.pVS = pVS;
+ GraphicsPipeline.pPS = pPS;
+
+ GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE;
+ GraphicsPipeline.RasterizerDesc.ScissorEnable = True;
+ GraphicsPipeline.DepthStencilDesc.DepthEnable = False;
+
+ auto& RT0 = GraphicsPipeline.BlendDesc.RenderTargets[0];
+ RT0.BlendEnable = True;
+ RT0.SrcBlend = BLEND_FACTOR_SRC_ALPHA;
+ RT0.DestBlend = BLEND_FACTOR_INV_SRC_ALPHA;
+ RT0.BlendOp = BLEND_OPERATION_ADD;
+ RT0.SrcBlendAlpha = BLEND_FACTOR_INV_SRC_ALPHA;
+ RT0.DestBlendAlpha = BLEND_FACTOR_ZERO;
+ RT0.BlendOpAlpha = BLEND_OPERATION_ADD;
+ RT0.RenderTargetWriteMask = COLOR_MASK_ALL;
+
+ LayoutElement VSInputs[] //
+ {
+ {0, 0, 2, VT_FLOAT32}, // pos
+ {1, 0, 2, VT_FLOAT32}, // uv
+ {2, 0, 4, VT_UINT8, True} // col
+ };
+ GraphicsPipeline.InputLayout.NumElements = _countof(VSInputs);
+ GraphicsPipeline.InputLayout.LayoutElements = VSInputs;
+
+ ShaderResourceVariableDesc Variables[] =
+ {
+ {SHADER_TYPE_PIXEL, "Texture", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE} //
+ };
+ PSODesc.ResourceLayout.Variables = Variables;
+ PSODesc.ResourceLayout.NumVariables = _countof(Variables);
+
+ SamplerDesc SamLinearWrap;
+ SamLinearWrap.AddressU = TEXTURE_ADDRESS_WRAP;
+ SamLinearWrap.AddressV = TEXTURE_ADDRESS_WRAP;
+ SamLinearWrap.AddressW = TEXTURE_ADDRESS_WRAP;
+ StaticSamplerDesc StaticSamplers[] =
+ {
+ {SHADER_TYPE_PIXEL, "Texture", SamLinearWrap} //
+ };
+ PSODesc.ResourceLayout.StaticSamplers = StaticSamplers;
+ PSODesc.ResourceLayout.NumStaticSamplers = _countof(StaticSamplers);
+
+ m_pDevice->CreatePipelineState(PSOCreateInfo, &m_pPSO);
+
+ {
+ BufferDesc BuffDesc;
+ BuffDesc.uiSizeInBytes = sizeof(float4x4);
+ BuffDesc.Usage = USAGE_DYNAMIC;
+ BuffDesc.BindFlags = BIND_UNIFORM_BUFFER;
+ BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pDevice->CreateBuffer(BuffDesc, nullptr, &m_pVertexConstantBuffer);
+ }
+ m_pPSO->GetStaticVariableByName(SHADER_TYPE_VERTEX, "Constants")->Set(m_pVertexConstantBuffer);
+
+ CreateFontsTexture();
+}
+
+void ImGuiDiligentRenderer::CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels = nullptr;
+ int width = 0, height = 0;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ TextureDesc FontTexDesc;
+ FontTexDesc.Name = "Imgui font texture";
+ FontTexDesc.Type = RESOURCE_DIM_TEX_2D;
+ FontTexDesc.Width = static_cast<Uint32>(width);
+ FontTexDesc.Height = static_cast<Uint32>(height);
+ FontTexDesc.Format = TEX_FORMAT_RGBA8_UNORM;
+ FontTexDesc.BindFlags = BIND_SHADER_RESOURCE;
+ FontTexDesc.Usage = USAGE_STATIC;
+
+ TextureSubResData Mip0Data[] = {{pixels, FontTexDesc.Width * 4}};
+ TextureData InitData(Mip0Data, _countof(Mip0Data));
+
+ RefCntAutoPtr<ITexture> pFontTex;
+ m_pDevice->CreateTexture(FontTexDesc, &InitData, &pFontTex);
+ m_pFontSRV = pFontTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE);
+
+ m_pSRB.Release();
+ m_pPSO->CreateShaderResourceBinding(&m_pSRB, true);
+ m_pSRB->GetVariableByName(SHADER_TYPE_PIXEL, "Texture")->Set(m_pFontSRV);
+
+ // Store our identifier
+ io.Fonts->TexID = (ImTextureID)m_pFontSRV;
+}
+
+float4 ImGuiDiligentRenderer::TransformClipRect(const ImVec2& DisplaySize, const float4& rect) const
+{
+ switch (m_SurfacePreTransform)
+ {
+ case SURFACE_TRANSFORM_IDENTITY:
+ return rect;
+
+ case SURFACE_TRANSFORM_ROTATE_90:
+ {
+ // The image content is rotated 90 degrees clockwise. The origin is in the left-top corner.
+ //
+ // DsplSz.y
+ // a.x -a.y a.y Old origin
+ // 0---->| 0------->|<------| /
+ // 0__|_____|____________________ 0__|________|_______|/
+ // | | ' | | | ' |
+ // a.y | | ' | a.x | | ' |
+ // _V_|_ _ _a____b | _V_|_ _d'___a' |
+ // A | | | | | | | |
+ // DsplSz.y | | |____| | | |____| |
+ // -a.y | | d c | | c' b' |
+ // _|_|__________________________| | |
+ // A | |
+ // |-----> Y' | |
+ // New Origin |________________|
+ //
+ float2 a{rect.x, rect.y};
+ float2 c{rect.z, rect.w};
+ return float4 //
+ {
+ DisplaySize.y - c.y, // min_x = c'.x
+ a.x, // min_y = a'.y
+ DisplaySize.y - a.y, // max_x = a'.x
+ c.x // max_y = c'.y
+ };
+ }
+
+ case SURFACE_TRANSFORM_ROTATE_180:
+ {
+ // The image content is rotated 180 degrees clockwise. The origin is in the left-top corner.
+ //
+ // a.x DsplSz.x - a.x
+ // 0---->| 0------------------>|
+ // 0__|_____|____________________ 0_ _|___________________|______
+ // | | ' | | | ' |
+ // a.y | | ' | DsplSz.y | | c'___d' |
+ // _V_|_ _ _a____b | -a.y | | | | |
+ // | | | | _V_|_ _ _ _ _ _ _ |____| |
+ // | |____| | | b' a' |
+ // | d c | | |
+ // |__________________________| |__________________________|
+ // A A
+ // | |
+ // New Origin Old Origin
+ float2 a{rect.x, rect.y};
+ float2 c{rect.z, rect.w};
+ return float4 //
+ {
+ DisplaySize.x - c.x, // min_x = c'.x
+ DisplaySize.y - c.y, // min_y = c'.y
+ DisplaySize.x - a.x, // max_x = a'.x
+ DisplaySize.y - a.y // max_y = a'.y
+ };
+ }
+
+ case SURFACE_TRANSFORM_ROTATE_270:
+ {
+ // The image content is rotated 270 degrees clockwise. The origin is in the left-top corner.
+ //
+ // 0 a.x DsplSz.x-a.x New Origin a.y
+ // |---->|<-------------------| 0----->|
+ // 0_ _|_____|____________________V 0 _|______|_________
+ // | | ' | | | ' |
+ // | | ' | | | ' |
+ // a.y_V_|_ _ _a____b | DsplSz.x | | ' |
+ // | | | | -a.x | | ' |
+ // | |____| | | | b'___c' |
+ // | d c | | | | | |
+ // DsplSz.y _ _|__________________________| _V_|_ _ _ |____| |
+ // | a' d' |
+ // | |
+ // |________________|
+ // A
+ // |
+ // Old origin
+ float2 a{rect.x, rect.y};
+ float2 c{rect.z, rect.w};
+ return float4 //
+ {
+ a.y, // min_x = a'.x
+ DisplaySize.x - c.x, // min_y = c'.y
+ c.y, // max_x = c'.x
+ DisplaySize.x - a.x // max_y = a'.y
+ };
+ }
+
+ case SURFACE_TRANSFORM_OPTIMAL:
+ UNEXPECTED("SURFACE_TRANSFORM_OPTIMAL is only valid as parameter during swap chain initialization.");
+ return rect;
+
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270:
+ UNEXPECTED("Mirror transforms are not supported");
+ return rect;
+
+ default:
+ UNEXPECTED("Unknown transform");
+ return rect;
+ }
+}
+
+void ImGuiDiligentRenderer::RenderDrawData(IDeviceContext* pCtx, ImDrawData* pDrawData)
+{
+ // Avoid rendering when minimized
+ if (pDrawData->DisplaySize.x <= 0.0f || pDrawData->DisplaySize.y <= 0.0f)
+ return;
+
+ // Create and grow vertex/index buffers if needed
+ if (!m_pVB || static_cast<int>(m_VertexBufferSize) < pDrawData->TotalVtxCount)
+ {
+ m_pVB.Release();
+ while (static_cast<int>(m_VertexBufferSize) < pDrawData->TotalVtxCount)
+ m_VertexBufferSize *= 2;
+
+ BufferDesc VBDesc;
+ VBDesc.Name = "Imgui vertex buffer";
+ VBDesc.BindFlags = BIND_VERTEX_BUFFER;
+ VBDesc.uiSizeInBytes = m_VertexBufferSize * sizeof(ImDrawVert);
+ VBDesc.Usage = USAGE_DYNAMIC;
+ VBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pDevice->CreateBuffer(VBDesc, nullptr, &m_pVB);
+ }
+
+ if (!m_pIB || static_cast<int>(m_IndexBufferSize) < pDrawData->TotalIdxCount)
+ {
+ m_pIB.Release();
+ while (static_cast<int>(m_IndexBufferSize) < pDrawData->TotalIdxCount)
+ m_IndexBufferSize *= 2;
+
+ BufferDesc IBDesc;
+ IBDesc.Name = "Imgui index buffer";
+ IBDesc.BindFlags = BIND_INDEX_BUFFER;
+ IBDesc.uiSizeInBytes = m_IndexBufferSize * sizeof(ImDrawIdx);
+ IBDesc.Usage = USAGE_DYNAMIC;
+ IBDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
+ m_pDevice->CreateBuffer(IBDesc, nullptr, &m_pIB);
+ }
+
+ {
+ MapHelper<ImDrawVert> Verices(pCtx, m_pVB, MAP_WRITE, MAP_FLAG_DISCARD);
+ MapHelper<ImDrawIdx> Indices(pCtx, m_pIB, MAP_WRITE, MAP_FLAG_DISCARD);
+
+ ImDrawVert* vtx_dst = Verices;
+ ImDrawIdx* idx_dst = Indices;
+ for (int n = 0; n < pDrawData->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = pDrawData->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ }
+
+ // Setup orthographic projection matrix into our constant buffer
+ // Our visible imgui space lies from pDrawData->DisplayPos (top left) to pDrawData->DisplayPos+data_data->DisplaySize (bottom right).
+ // DisplayPos is (0,0) for single viewport apps.
+ {
+ // DisplaySize always refers to the logical dimensions that account for pre-transform, hence
+ // the aspect ratio will be correct after applying appropriate rotation.
+ float L = pDrawData->DisplayPos.x;
+ float R = pDrawData->DisplayPos.x + pDrawData->DisplaySize.x;
+ float T = pDrawData->DisplayPos.y;
+ float B = pDrawData->DisplayPos.y + pDrawData->DisplaySize.y;
+
+ // clang-format off
+ float4x4 Projection
+ {
+ 2.0f / (R - L), 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f / (T - B), 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.0f,
+ (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f
+ };
+ // clang-format on
+
+ // Bake pre-transform into projection
+ switch (m_SurfacePreTransform)
+ {
+ case SURFACE_TRANSFORM_IDENTITY:
+ // Nothing to do
+ break;
+
+ case SURFACE_TRANSFORM_ROTATE_90:
+ // The image content is rotated 90 degrees clockwise.
+ Projection *= float4x4::RotationZ(-PI_F * 0.5f);
+ break;
+
+ case SURFACE_TRANSFORM_ROTATE_180:
+ // The image content is rotated 180 degrees clockwise.
+ Projection *= float4x4::RotationZ(-PI_F * 1.0f);
+ break;
+
+ case SURFACE_TRANSFORM_ROTATE_270:
+ // The image content is rotated 270 degrees clockwise.
+ Projection *= float4x4::RotationZ(-PI_F * 1.5f);
+ break;
+
+ case SURFACE_TRANSFORM_OPTIMAL:
+ UNEXPECTED("SURFACE_TRANSFORM_OPTIMAL is only valid as parameter during swap chain initialization.");
+ break;
+
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180:
+ case SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270:
+ UNEXPECTED("Mirror transforms are not supported");
+ break;
+
+ default:
+ UNEXPECTED("Unknown transform");
+ }
+
+ MapHelper<float4x4> CBData(pCtx, m_pVertexConstantBuffer, MAP_WRITE, MAP_FLAG_DISCARD);
+ *CBData = Projection;
+ }
+
+ auto SetupRenderState = [&]() //
+ {
+ // Setup shader and vertex buffers
+ Uint32 Offsets[] = {0};
+ IBuffer* pVBs[] = {m_pVB};
+ pCtx->SetVertexBuffers(0, 1, pVBs, Offsets, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, SET_VERTEX_BUFFERS_FLAG_RESET);
+ pCtx->SetIndexBuffer(m_pIB, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+ pCtx->SetPipelineState(m_pPSO);
+ pCtx->CommitShaderResources(m_pSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+
+ const float blend_factor[4] = {0.f, 0.f, 0.f, 0.f};
+ pCtx->SetBlendFactors(blend_factor);
+
+ Viewport vp;
+ vp.Width = static_cast<float>(m_RenderSurfaceWidth) * pDrawData->FramebufferScale.x;
+ vp.Height = static_cast<float>(m_RenderSurfaceHeight) * pDrawData->FramebufferScale.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0;
+ pCtx->SetViewports(1,
+ &vp,
+ static_cast<Uint32>(m_RenderSurfaceWidth * pDrawData->FramebufferScale.x),
+ static_cast<Uint32>(m_RenderSurfaceHeight * pDrawData->FramebufferScale.y));
+ };
+
+ SetupRenderState();
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_idx_offset = 0;
+ int global_vtx_offset = 0;
+
+ for (int n = 0; n < pDrawData->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = pDrawData->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // 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)
+ SetupRenderState();
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Apply scissor/clipping rectangle
+ float4 ClipRect //
+ {
+ (pcmd->ClipRect.x - pDrawData->DisplayPos.x) * pDrawData->FramebufferScale.x,
+ (pcmd->ClipRect.y - pDrawData->DisplayPos.y) * pDrawData->FramebufferScale.y,
+ (pcmd->ClipRect.z - pDrawData->DisplayPos.x) * pDrawData->FramebufferScale.x,
+ (pcmd->ClipRect.w - pDrawData->DisplayPos.y) * pDrawData->FramebufferScale.y //
+ };
+ // Apply pretransform
+ ClipRect = TransformClipRect(pDrawData->DisplaySize, ClipRect);
+
+ Rect r //
+ {
+ static_cast<Int32>(ClipRect.x),
+ static_cast<Int32>(ClipRect.y),
+ static_cast<Int32>(ClipRect.z),
+ static_cast<Int32>(ClipRect.w) //
+ };
+ pCtx->SetScissorRects(1,
+ &r,
+ static_cast<Uint32>(m_RenderSurfaceWidth * pDrawData->FramebufferScale.x),
+ static_cast<Uint32>(m_RenderSurfaceHeight * pDrawData->FramebufferScale.y));
+
+ // Bind texture, Draw
+ auto* texture_srv = reinterpret_cast<ITextureView*>(pcmd->TextureId);
+ VERIFY_EXPR(texture_srv == m_pFontSRV);
+ (void)texture_srv;
+ //ctx->PSSetShaderResources(0, 1, &texture_srv);
+ DrawIndexedAttribs DrawAttrs(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? VT_UINT16 : VT_UINT32, DRAW_FLAG_VERIFY_STATES);
+ DrawAttrs.FirstIndexLocation = pcmd->IdxOffset + global_idx_offset;
+ DrawAttrs.BaseVertex = pcmd->VtxOffset + global_vtx_offset;
+ pCtx->DrawIndexed(DrawAttrs);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+}
+
+} // namespace Diligent