Examples: DirectX10: Save/restore state + minor cleanups (#570)

This commit is contained in:
ocornut 2016-04-03 12:59:56 +02:00
parent 90493f8add
commit 518f32ccfe
1 changed files with 86 additions and 43 deletions

View File

@ -46,6 +46,8 @@ struct VERTEX_CONSTANT_BUFFER
// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f)
void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
{ {
ID3D10Device* ctx = g_pd3dDevice;
// Create and grow vertex/index buffers if needed // Create and grow vertex/index buffers if needed
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{ {
@ -58,7 +60,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
desc.MiscFlags = 0; desc.MiscFlags = 0;
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
return; return;
} }
@ -66,13 +68,13 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
{ {
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000; g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
D3D10_BUFFER_DESC bufferDesc; D3D10_BUFFER_DESC desc;
memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
bufferDesc.Usage = D3D10_USAGE_DYNAMIC; desc.Usage = D3D10_USAGE_DYNAMIC;
bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
return; return;
} }
@ -81,7 +83,6 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
ImDrawIdx* idx_dst = NULL; ImDrawIdx* idx_dst = NULL;
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
{ {
const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawList* cmd_list = draw_data->CmdLists[n];
@ -95,11 +96,10 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
// Setup orthographic projection matrix into our constant buffer // Setup orthographic projection matrix into our constant buffer
{ {
void* mappedResource; void* mapped_resource;
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
return; return;
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource;
const float L = 0.0f; const float L = 0.0f;
const float R = ImGui::GetIO().DisplaySize.x; const float R = ImGui::GetIO().DisplaySize.x;
const float B = ImGui::GetIO().DisplaySize.y; const float B = ImGui::GetIO().DisplaySize.y;
@ -111,39 +111,72 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
{ 0.0f, 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, 0.5f, 0.0f },
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
}; };
memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
g_pVertexConstantBuffer->Unmap(); g_pVertexConstantBuffer->Unmap();
} }
// Setup viewport // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
struct BACKUP_DX10_STATE
{ {
D3D10_VIEWPORT vp; UINT ScissorRectsCount, ViewportsCount;
memset(&vp, 0, sizeof(D3D10_VIEWPORT)); D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; ID3D10RasterizerState* RS;
vp.MinDepth = 0.0f; ID3D10BlendState* BlendState;
vp.MaxDepth = 1.0f; FLOAT BlendFactor[4];
vp.TopLeftX = 0; UINT SampleMask;
vp.TopLeftY = 0; ID3D10ShaderResourceView* PSShaderResource;
g_pd3dDevice->RSSetViewports(1, &vp); ID3D10SamplerState* PSSampler;
} ID3D10PixelShader* PS;
ID3D10VertexShader* VS;
D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
DXGI_FORMAT IndexBufferFormat;
ID3D10InputLayout* InputLayout;
};
BACKUP_DX10_STATE old;
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
ctx->RSGetState(&old.RS);
ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
ctx->PSGetSamplers(0, 1, &old.PSSampler);
ctx->PSGetShader(&old.PS);
ctx->VSGetShader(&old.VS);
ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
ctx->IAGetInputLayout(&old.InputLayout);
// Setup viewport
D3D10_VIEWPORT vp;
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
vp.Width = (UINT)ImGui::GetIO().DisplaySize.x;
vp.Height = (UINT)ImGui::GetIO().DisplaySize.y;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = vp.TopLeftY = 0;
ctx->RSSetViewports(1, &vp);
// Bind shader and vertex buffers // Bind shader and vertex buffers
unsigned int stride = sizeof(ImDrawVert); unsigned int stride = sizeof(ImDrawVert);
unsigned int offset = 0; unsigned int offset = 0;
g_pd3dDevice->IASetInputLayout(g_pInputLayout); ctx->IASetInputLayout(g_pInputLayout);
g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
g_pd3dDevice->VSSetShader(g_pVertexShader); ctx->VSSetShader(g_pVertexShader);
g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
g_pd3dDevice->PSSetShader(g_pPixelShader); ctx->PSSetShader(g_pPixelShader);
g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); ctx->PSSetSamplers(0, 1, &g_pFontSampler);
// Setup render state // Setup render state
const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
g_pd3dDevice->RSSetState(g_pRasterizerState); ctx->RSSetState(g_pRasterizerState);
// Render command lists // Render command lists
int vtx_offset = 0; int vtx_offset = 0;
@ -161,19 +194,29 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data)
else else
{ {
const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w };
g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId);
g_pd3dDevice->RSSetScissorRects(1, &r); ctx->RSSetScissorRects(1, &r);
g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset);
} }
idx_offset += pcmd->ElemCount; idx_offset += pcmd->ElemCount;
} }
vtx_offset += cmd_list->VtxBuffer.size(); vtx_offset += cmd_list->VtxBuffer.size();
} }
// Restore modified state // Restore modified DX state
g_pd3dDevice->IASetInputLayout(NULL); ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
g_pd3dDevice->PSSetShader(NULL); ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
g_pd3dDevice->VSSetShader(NULL); ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
} }
IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam)