Skip to content

Commit

Permalink
Backends: DX9: programmable rendering pipeline: 6.state backup & restore
Browse files Browse the repository at this point in the history
  • Loading branch information
Kuanlan authored and Kuanlan committed Mar 11, 2021
1 parent 2bcb760 commit 7716489
Showing 1 changed file with 46 additions and 19 deletions.
65 changes: 46 additions & 19 deletions backends/imgui_impl_dx9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ static IDirect3DVertexBuffer9* g_pVB = NULL;
static IDirect3DIndexBuffer9* g_pIB = NULL;
static int g_VertexBufferSize = 4096;
static int g_IndexBufferSize = 8192;
// Direct3D9 state
static IDirect3DStateBlock9* g_pd3dState = NULL;
static D3DMATRIX g_LastMVP[3];
// Direct3D9 programmable rendering pipeline data
static bool g_IsShaderPipeline = false;
static IDirect3DVertexDeclaration9* g_pInputLayout = NULL;
Expand All @@ -210,6 +213,43 @@ static const char* IMGUI_IMPL_D3D9_BACKEND_NAME_FIXED = "imgui_impl_dx9 (fixed)"
static const char* IMGUI_IMPL_D3D9_BACKEND_NAME_SHADER = "imgui_impl_dx9 (shader)";

// Setup render state
// According to Microsoft's official documents, IDirect3DStateBlock9 should store all states,
// but according to the actual test, it seems to only store dirty states.
// We have to backup some states manually. Only support those device create without D3DCREATE_PUREDEVICE flag!
static void ImGui_ImplDX9_BackupState()
{
// Backup the DX9 transform
if (!g_IsShaderPipeline)
{
g_pd3dDevice->GetTransform(D3DTS_WORLD, &g_LastMVP[0]);
g_pd3dDevice->GetTransform(D3DTS_VIEW, &g_LastMVP[1]);
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &g_LastMVP[2]);
}
else
{
g_pd3dDevice->GetVertexShaderConstantF(0, (float*)&g_LastMVP[0], 4);
}

// Backup the DX9 state
g_pd3dState->Capture();
}
static void ImGui_ImplDX9_RestoreState()
{
// Restore the DX9 transform
if (!g_IsShaderPipeline)
{
g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_LastMVP[0]);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &g_LastMVP[1]);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &g_LastMVP[2]);
}
else
{
g_pd3dDevice->SetVertexShaderConstantF(0, (float*)&g_LastMVP[0], 4);
}

// Restore the DX9 state
g_pd3dState->Apply();
}
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
{
IDirect3DDevice9* ctx = g_pd3dDevice;
Expand Down Expand Up @@ -491,18 +531,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
if (!ImGui_ImplDX9_CreateBuffers(draw_data))
return;

// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
D3DMATRIX last_world, last_view, last_projection;
g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);

// Backup the DX9 state
IDirect3DStateBlock9* d3d9_state_block = NULL;
if (D3D_OK != g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block))
return;

// Setup desired DX state
ImGui_ImplDX9_BackupState();
ImGui_ImplDX9_SetupRenderState(draw_data);

// Render command lists
Expand Down Expand Up @@ -537,14 +567,8 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
global_vtx_offset += cmd_list->VtxBuffer.Size;
}

// Restore the DX9 transform
g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);

// Restore the DX9 state
d3d9_state_block->Apply();
d3d9_state_block->Release();
// Restore DX state
ImGui_ImplDX9_RestoreState();
}

bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
Expand Down Expand Up @@ -573,6 +597,8 @@ bool ImGui_ImplDX9_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (D3D_OK != g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &g_pd3dState))
return false;
if (!ImGui_ImplDX9_CreateFontsTexture())
return false;
g_IsShaderPipeline = ImGui_ImplDX9_CreateShaderPipeline(); // Shader pipeline is optional
Expand All @@ -591,6 +617,7 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
SAFE_RELEASE(g_pIB);
g_VertexBufferSize = 4096;
g_IndexBufferSize = 8192;
SAFE_RELEASE(g_pd3dState);
g_IsShaderPipeline = false;
SAFE_RELEASE(g_pInputLayout);
SAFE_RELEASE(g_pVertexShader);
Expand Down

0 comments on commit 7716489

Please sign in to comment.