imgui_impl_dx10.cpp (24411B)
1 // dear imgui: Renderer Backend for DirectX10 2 // This needs to be used along with a Platform Backend (e.g. Win32) 3 4 // Implemented features: 5 // [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 // [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices. 7 8 // You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 9 // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. 10 // Read online: https://github.com/ocornut/imgui/tree/master/docs 11 12 // CHANGELOG 13 // (minor and older changes stripped away, please see git history for details) 14 // 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 15 // 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer. 16 // 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData(). 17 // 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 18 // 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 19 // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). 20 // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 21 // 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions. 22 // 2018-06-08: Misc: Extracted imgui_impl_dx10.cpp/.h away from the old combined DX10+Win32 example. 23 // 2018-06-08: DirectX10: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 24 // 2018-04-09: Misc: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) on other backends. 25 // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. 26 // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 27 // 2016-05-07: DirectX10: Disabling depth-write. 28 29 #include "imgui.h" 30 #include "imgui_impl_dx10.h" 31 32 // DirectX 33 #include <stdio.h> 34 #include <d3d10_1.h> 35 #include <d3d10.h> 36 #include <d3dcompiler.h> 37 #ifdef _MSC_VER 38 #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. 39 #endif 40 41 // DirectX data 42 static ID3D10Device* g_pd3dDevice = NULL; 43 static IDXGIFactory* g_pFactory = NULL; 44 static ID3D10Buffer* g_pVB = NULL; 45 static ID3D10Buffer* g_pIB = NULL; 46 static ID3D10VertexShader* g_pVertexShader = NULL; 47 static ID3D10InputLayout* g_pInputLayout = NULL; 48 static ID3D10Buffer* g_pVertexConstantBuffer = NULL; 49 static ID3D10PixelShader* g_pPixelShader = NULL; 50 static ID3D10SamplerState* g_pFontSampler = NULL; 51 static ID3D10ShaderResourceView*g_pFontTextureView = NULL; 52 static ID3D10RasterizerState* g_pRasterizerState = NULL; 53 static ID3D10BlendState* g_pBlendState = NULL; 54 static ID3D10DepthStencilState* g_pDepthStencilState = NULL; 55 static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000; 56 57 struct VERTEX_CONSTANT_BUFFER 58 { 59 float mvp[4][4]; 60 }; 61 62 static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx) 63 { 64 // Setup viewport 65 D3D10_VIEWPORT vp; 66 memset(&vp, 0, sizeof(D3D10_VIEWPORT)); 67 vp.Width = (UINT)draw_data->DisplaySize.x; 68 vp.Height = (UINT)draw_data->DisplaySize.y; 69 vp.MinDepth = 0.0f; 70 vp.MaxDepth = 1.0f; 71 vp.TopLeftX = vp.TopLeftY = 0; 72 ctx->RSSetViewports(1, &vp); 73 74 // Bind shader and vertex buffers 75 unsigned int stride = sizeof(ImDrawVert); 76 unsigned int offset = 0; 77 ctx->IASetInputLayout(g_pInputLayout); 78 ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); 79 ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 80 ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 81 ctx->VSSetShader(g_pVertexShader); 82 ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); 83 ctx->PSSetShader(g_pPixelShader); 84 ctx->PSSetSamplers(0, 1, &g_pFontSampler); 85 ctx->GSSetShader(NULL); 86 87 // Setup render state 88 const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 89 ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); 90 ctx->OMSetDepthStencilState(g_pDepthStencilState, 0); 91 ctx->RSSetState(g_pRasterizerState); 92 } 93 94 // Render function 95 void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) 96 { 97 // Avoid rendering when minimized 98 if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 99 return; 100 101 ID3D10Device* ctx = g_pd3dDevice; 102 103 // Create and grow vertex/index buffers if needed 104 if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) 105 { 106 if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 107 g_VertexBufferSize = draw_data->TotalVtxCount + 5000; 108 D3D10_BUFFER_DESC desc; 109 memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); 110 desc.Usage = D3D10_USAGE_DYNAMIC; 111 desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert); 112 desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; 113 desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; 114 desc.MiscFlags = 0; 115 if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) 116 return; 117 } 118 119 if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount) 120 { 121 if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 122 g_IndexBufferSize = draw_data->TotalIdxCount + 10000; 123 D3D10_BUFFER_DESC desc; 124 memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); 125 desc.Usage = D3D10_USAGE_DYNAMIC; 126 desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); 127 desc.BindFlags = D3D10_BIND_INDEX_BUFFER; 128 desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; 129 if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) 130 return; 131 } 132 133 // Copy and convert all vertices into a single contiguous buffer 134 ImDrawVert* vtx_dst = NULL; 135 ImDrawIdx* idx_dst = NULL; 136 g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); 137 g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); 138 for (int n = 0; n < draw_data->CmdListsCount; n++) 139 { 140 const ImDrawList* cmd_list = draw_data->CmdLists[n]; 141 memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); 142 memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 143 vtx_dst += cmd_list->VtxBuffer.Size; 144 idx_dst += cmd_list->IdxBuffer.Size; 145 } 146 g_pVB->Unmap(); 147 g_pIB->Unmap(); 148 149 // Setup orthographic projection matrix into our constant buffer 150 // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 151 { 152 void* mapped_resource; 153 if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 154 return; 155 VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; 156 float L = draw_data->DisplayPos.x; 157 float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 158 float T = draw_data->DisplayPos.y; 159 float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 160 float mvp[4][4] = 161 { 162 { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 163 { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 164 { 0.0f, 0.0f, 0.5f, 0.0f }, 165 { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, 166 }; 167 memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 168 g_pVertexConstantBuffer->Unmap(); 169 } 170 171 // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 172 struct BACKUP_DX10_STATE 173 { 174 UINT ScissorRectsCount, ViewportsCount; 175 D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 176 D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 177 ID3D10RasterizerState* RS; 178 ID3D10BlendState* BlendState; 179 FLOAT BlendFactor[4]; 180 UINT SampleMask; 181 UINT StencilRef; 182 ID3D10DepthStencilState* DepthStencilState; 183 ID3D10ShaderResourceView* PSShaderResource; 184 ID3D10SamplerState* PSSampler; 185 ID3D10PixelShader* PS; 186 ID3D10VertexShader* VS; 187 ID3D10GeometryShader* GS; 188 D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; 189 ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; 190 UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 191 DXGI_FORMAT IndexBufferFormat; 192 ID3D10InputLayout* InputLayout; 193 }; 194 BACKUP_DX10_STATE old = {}; 195 old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 196 ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 197 ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); 198 ctx->RSGetState(&old.RS); 199 ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 200 ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 201 ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); 202 ctx->PSGetSamplers(0, 1, &old.PSSampler); 203 ctx->PSGetShader(&old.PS); 204 ctx->VSGetShader(&old.VS); 205 ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 206 ctx->GSGetShader(&old.GS); 207 ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); 208 ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 209 ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 210 ctx->IAGetInputLayout(&old.InputLayout); 211 212 // Setup desired DX state 213 ImGui_ImplDX10_SetupRenderState(draw_data, ctx); 214 215 // Render command lists 216 // (Because we merged all buffers into a single one, we maintain our own offset into them) 217 int global_vtx_offset = 0; 218 int global_idx_offset = 0; 219 ImVec2 clip_off = draw_data->DisplayPos; 220 for (int n = 0; n < draw_data->CmdListsCount; n++) 221 { 222 const ImDrawList* cmd_list = draw_data->CmdLists[n]; 223 for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) 224 { 225 const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; 226 if (pcmd->UserCallback) 227 { 228 // User callback, registered via ImDrawList::AddCallback() 229 // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 230 if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 231 ImGui_ImplDX10_SetupRenderState(draw_data, ctx); 232 else 233 pcmd->UserCallback(cmd_list, pcmd); 234 } 235 else 236 { 237 // Apply scissor/clipping rectangle 238 const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y)}; 239 ctx->RSSetScissorRects(1, &r); 240 241 // Bind texture, Draw 242 ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID(); 243 ctx->PSSetShaderResources(0, 1, &texture_srv); 244 ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); 245 } 246 } 247 global_idx_offset += cmd_list->IdxBuffer.Size; 248 global_vtx_offset += cmd_list->VtxBuffer.Size; 249 } 250 251 // Restore modified DX state 252 ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 253 ctx->RSSetViewports(old.ViewportsCount, old.Viewports); 254 ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); 255 ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 256 ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 257 ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 258 ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 259 ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); 260 ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); 261 ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release(); 262 ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 263 ctx->IASetPrimitiveTopology(old.PrimitiveTopology); 264 ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 265 ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 266 ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 267 } 268 269 static void ImGui_ImplDX10_CreateFontsTexture() 270 { 271 // Build texture atlas 272 ImGuiIO& io = ImGui::GetIO(); 273 unsigned char* pixels; 274 int width, height; 275 io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 276 277 // Upload texture to graphics system 278 { 279 D3D10_TEXTURE2D_DESC desc; 280 ZeroMemory(&desc, sizeof(desc)); 281 desc.Width = width; 282 desc.Height = height; 283 desc.MipLevels = 1; 284 desc.ArraySize = 1; 285 desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 286 desc.SampleDesc.Count = 1; 287 desc.Usage = D3D10_USAGE_DEFAULT; 288 desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; 289 desc.CPUAccessFlags = 0; 290 291 ID3D10Texture2D* pTexture = NULL; 292 D3D10_SUBRESOURCE_DATA subResource; 293 subResource.pSysMem = pixels; 294 subResource.SysMemPitch = desc.Width * 4; 295 subResource.SysMemSlicePitch = 0; 296 g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 297 IM_ASSERT(pTexture != NULL); 298 299 // Create texture view 300 D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; 301 ZeroMemory(&srv_desc, sizeof(srv_desc)); 302 srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 303 srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; 304 srv_desc.Texture2D.MipLevels = desc.MipLevels; 305 srv_desc.Texture2D.MostDetailedMip = 0; 306 g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); 307 pTexture->Release(); 308 } 309 310 // Store our identifier 311 io.Fonts->SetTexID((ImTextureID)g_pFontTextureView); 312 313 // Create texture sampler 314 { 315 D3D10_SAMPLER_DESC desc; 316 ZeroMemory(&desc, sizeof(desc)); 317 desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; 318 desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; 319 desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; 320 desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; 321 desc.MipLODBias = 0.f; 322 desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; 323 desc.MinLOD = 0.f; 324 desc.MaxLOD = 0.f; 325 g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); 326 } 327 } 328 329 bool ImGui_ImplDX10_CreateDeviceObjects() 330 { 331 if (!g_pd3dDevice) 332 return false; 333 if (g_pFontSampler) 334 ImGui_ImplDX10_InvalidateDeviceObjects(); 335 336 // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 337 // If you would like to use this DX10 sample code but remove this dependency you can: 338 // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 339 // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 340 // See https://github.com/ocornut/imgui/pull/638 for sources and details. 341 342 // Create the vertex shader 343 { 344 static const char* vertexShader = 345 "cbuffer vertexBuffer : register(b0) \ 346 {\ 347 float4x4 ProjectionMatrix; \ 348 };\ 349 struct VS_INPUT\ 350 {\ 351 float2 pos : POSITION;\ 352 float4 col : COLOR0;\ 353 float2 uv : TEXCOORD0;\ 354 };\ 355 \ 356 struct PS_INPUT\ 357 {\ 358 float4 pos : SV_POSITION;\ 359 float4 col : COLOR0;\ 360 float2 uv : TEXCOORD0;\ 361 };\ 362 \ 363 PS_INPUT main(VS_INPUT input)\ 364 {\ 365 PS_INPUT output;\ 366 output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ 367 output.col = input.col;\ 368 output.uv = input.uv;\ 369 return output;\ 370 }"; 371 372 ID3DBlob* vertexShaderBlob; 373 if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL))) 374 return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 375 if (g_pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK) 376 { 377 vertexShaderBlob->Release(); 378 return false; 379 } 380 381 // Create the input layout 382 D3D10_INPUT_ELEMENT_DESC local_layout[] = 383 { 384 { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, 385 { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, 386 { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, 387 }; 388 if (g_pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) 389 { 390 vertexShaderBlob->Release(); 391 return false; 392 } 393 vertexShaderBlob->Release(); 394 395 // Create the constant buffer 396 { 397 D3D10_BUFFER_DESC desc; 398 desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); 399 desc.Usage = D3D10_USAGE_DYNAMIC; 400 desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; 401 desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; 402 desc.MiscFlags = 0; 403 g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); 404 } 405 } 406 407 // Create the pixel shader 408 { 409 static const char* pixelShader = 410 "struct PS_INPUT\ 411 {\ 412 float4 pos : SV_POSITION;\ 413 float4 col : COLOR0;\ 414 float2 uv : TEXCOORD0;\ 415 };\ 416 sampler sampler0;\ 417 Texture2D texture0;\ 418 \ 419 float4 main(PS_INPUT input) : SV_Target\ 420 {\ 421 float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ 422 return out_col; \ 423 }"; 424 425 ID3DBlob* pixelShaderBlob; 426 if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL))) 427 return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 428 if (g_pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK) 429 { 430 pixelShaderBlob->Release(); 431 return false; 432 } 433 pixelShaderBlob->Release(); 434 } 435 436 // Create the blending setup 437 { 438 D3D10_BLEND_DESC desc; 439 ZeroMemory(&desc, sizeof(desc)); 440 desc.AlphaToCoverageEnable = false; 441 desc.BlendEnable[0] = true; 442 desc.SrcBlend = D3D10_BLEND_SRC_ALPHA; 443 desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA; 444 desc.BlendOp = D3D10_BLEND_OP_ADD; 445 desc.SrcBlendAlpha = D3D10_BLEND_ONE; 446 desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA; 447 desc.BlendOpAlpha = D3D10_BLEND_OP_ADD; 448 desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL; 449 g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState); 450 } 451 452 // Create the rasterizer state 453 { 454 D3D10_RASTERIZER_DESC desc; 455 ZeroMemory(&desc, sizeof(desc)); 456 desc.FillMode = D3D10_FILL_SOLID; 457 desc.CullMode = D3D10_CULL_NONE; 458 desc.ScissorEnable = true; 459 desc.DepthClipEnable = true; 460 g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState); 461 } 462 463 // Create depth-stencil State 464 { 465 D3D10_DEPTH_STENCIL_DESC desc; 466 ZeroMemory(&desc, sizeof(desc)); 467 desc.DepthEnable = false; 468 desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL; 469 desc.DepthFunc = D3D10_COMPARISON_ALWAYS; 470 desc.StencilEnable = false; 471 desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP; 472 desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS; 473 desc.BackFace = desc.FrontFace; 474 g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState); 475 } 476 477 ImGui_ImplDX10_CreateFontsTexture(); 478 479 return true; 480 } 481 482 void ImGui_ImplDX10_InvalidateDeviceObjects() 483 { 484 if (!g_pd3dDevice) 485 return; 486 487 if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } 488 if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. 489 if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } 490 if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } 491 492 if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; } 493 if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; } 494 if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; } 495 if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } 496 if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } 497 if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } 498 if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } 499 } 500 501 bool ImGui_ImplDX10_Init(ID3D10Device* device) 502 { 503 // Setup backend capabilities flags 504 ImGuiIO& io = ImGui::GetIO(); 505 io.BackendRendererName = "imgui_impl_dx10"; 506 io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 507 508 // Get factory from device 509 IDXGIDevice* pDXGIDevice = NULL; 510 IDXGIAdapter* pDXGIAdapter = NULL; 511 IDXGIFactory* pFactory = NULL; 512 513 if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) 514 if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) 515 if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) 516 { 517 g_pd3dDevice = device; 518 g_pFactory = pFactory; 519 } 520 if (pDXGIDevice) pDXGIDevice->Release(); 521 if (pDXGIAdapter) pDXGIAdapter->Release(); 522 g_pd3dDevice->AddRef(); 523 524 return true; 525 } 526 527 void ImGui_ImplDX10_Shutdown() 528 { 529 ImGui_ImplDX10_InvalidateDeviceObjects(); 530 if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; } 531 if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } 532 } 533 534 void ImGui_ImplDX10_NewFrame() 535 { 536 if (!g_pFontSampler) 537 ImGui_ImplDX10_CreateDeviceObjects(); 538 }