mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-12-27 02:44:16 +08:00
3a0d9c55c1
If you really want to use d3dcompile, then I think its better to find the most recent d3dcompile you have on your computer and load its D3DCompile function. This process is now automatically handled. Just define the right Preprocessor.
556 lines
24 KiB
C++
556 lines
24 KiB
C++
// dear imgui: Renderer for DirectX10
|
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
|
|
|
// Implemented features:
|
|
// [X] Renderer: User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
|
|
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices.
|
|
|
|
// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
|
|
// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
|
|
// https://github.com/ocornut/imgui
|
|
|
|
// CHANGELOG
|
|
// (minor and older changes stripped away, please see git history for details)
|
|
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
|
// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
|
// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
|
|
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
|
|
// 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions.
|
|
// 2018-06-08: Misc: Extracted imgui_impl_dx10.cpp/.h away from the old combined DX10+Win32 example.
|
|
// 2018-06-08: DirectX10: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
|
// 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 back-ends.
|
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself.
|
|
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
|
// 2016-05-07: DirectX10: Disabling depth-write.
|
|
|
|
#include "../imgui.h"
|
|
#include "imgui_impl_dx10.h"
|
|
|
|
// DirectX
|
|
#include <stdio.h>
|
|
#include <d3d10_1.h>
|
|
#include <d3d10.h>
|
|
|
|
#include "../../overlay_experimental/ImGui_ShaderBlobs.h"
|
|
|
|
#ifdef USE_D3DCOMPILE
|
|
static ID3DBlob* g_pVertexShaderBlob = NULL;
|
|
static ID3DBlob* g_pPixelShaderBlob = NULL;
|
|
#endif
|
|
|
|
// DirectX data
|
|
static ID3D10Device* g_pd3dDevice = NULL;
|
|
static IDXGIFactory* g_pFactory = NULL;
|
|
static ID3D10Buffer* g_pVB = NULL;
|
|
static ID3D10Buffer* g_pIB = NULL;
|
|
static ID3D10VertexShader* g_pVertexShader = NULL;
|
|
static ID3D10InputLayout* g_pInputLayout = NULL;
|
|
static ID3D10Buffer* g_pVertexConstantBuffer = NULL;
|
|
static ID3D10PixelShader* g_pPixelShader = NULL;
|
|
static ID3D10SamplerState* g_pFontSampler = NULL;
|
|
static ID3D10ShaderResourceView*g_pFontTextureView = NULL;
|
|
static ID3D10RasterizerState* g_pRasterizerState = NULL;
|
|
static ID3D10BlendState* g_pBlendState = NULL;
|
|
static ID3D10DepthStencilState* g_pDepthStencilState = NULL;
|
|
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
|
|
|
struct VERTEX_CONSTANT_BUFFER
|
|
{
|
|
float mvp[4][4];
|
|
};
|
|
|
|
static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
|
|
{
|
|
// Setup viewport
|
|
D3D10_VIEWPORT vp;
|
|
memset(&vp, 0, sizeof(D3D10_VIEWPORT));
|
|
vp.Width = (UINT)draw_data->DisplaySize.x;
|
|
vp.Height = (UINT)draw_data->DisplaySize.y;
|
|
vp.MinDepth = 0.0f;
|
|
vp.MaxDepth = 1.0f;
|
|
vp.TopLeftX = vp.TopLeftY = 0;
|
|
ctx->RSSetViewports(1, &vp);
|
|
|
|
// Bind shader and vertex buffers
|
|
unsigned int stride = sizeof(ImDrawVert);
|
|
unsigned int offset = 0;
|
|
ctx->IASetInputLayout(g_pInputLayout);
|
|
ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset);
|
|
ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
|
|
ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
ctx->VSSetShader(g_pVertexShader);
|
|
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
|
ctx->PSSetShader(g_pPixelShader);
|
|
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
|
|
|
// Setup render state
|
|
const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
|
|
ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff);
|
|
ctx->OMSetDepthStencilState(g_pDepthStencilState, 0);
|
|
ctx->RSSetState(g_pRasterizerState);
|
|
}
|
|
|
|
// Render function
|
|
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
|
void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
|
{
|
|
// Avoid rendering when minimized
|
|
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
|
return;
|
|
|
|
ID3D10Device* ctx = g_pd3dDevice;
|
|
|
|
// Create and grow vertex/index buffers if needed
|
|
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
|
|
{
|
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
|
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
|
D3D10_BUFFER_DESC desc;
|
|
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
|
desc.Usage = D3D10_USAGE_DYNAMIC;
|
|
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
|
desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
|
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
|
desc.MiscFlags = 0;
|
|
if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0)
|
|
return;
|
|
}
|
|
|
|
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
|
|
{
|
|
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
|
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
|
D3D10_BUFFER_DESC desc;
|
|
memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
|
|
desc.Usage = D3D10_USAGE_DYNAMIC;
|
|
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
|
desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
|
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
|
if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
|
return;
|
|
}
|
|
|
|
// Copy and convert all vertices into a single contiguous buffer
|
|
ImDrawVert* vtx_dst = NULL;
|
|
ImDrawIdx* idx_dst = NULL;
|
|
g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
|
|
g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
|
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
{
|
|
const ImDrawList* cmd_list = draw_data->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;
|
|
}
|
|
g_pVB->Unmap();
|
|
g_pIB->Unmap();
|
|
|
|
// Setup orthographic projection matrix into our constant buffer
|
|
// 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.
|
|
{
|
|
void* mapped_resource;
|
|
if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
|
return;
|
|
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
|
|
float L = draw_data->DisplayPos.x;
|
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
|
float T = draw_data->DisplayPos.y;
|
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
|
float mvp[4][4] =
|
|
{
|
|
{ 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 },
|
|
};
|
|
memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
|
|
g_pVertexConstantBuffer->Unmap();
|
|
}
|
|
|
|
// 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
|
|
{
|
|
UINT ScissorRectsCount, ViewportsCount;
|
|
D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
ID3D10RasterizerState* RS;
|
|
ID3D10BlendState* BlendState;
|
|
FLOAT BlendFactor[4];
|
|
UINT SampleMask;
|
|
UINT StencilRef;
|
|
ID3D10DepthStencilState* DepthStencilState;
|
|
ID3D10ShaderResourceView* PSShaderResource;
|
|
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->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
|
|
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 desired DX state
|
|
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
|
|
|
// Render command lists
|
|
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
|
int global_vtx_offset = 0;
|
|
int global_idx_offset = 0;
|
|
ImVec2 clip_off = draw_data->DisplayPos;
|
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
|
{
|
|
const ImDrawList* cmd_list = draw_data->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)
|
|
{
|
|
// 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)
|
|
ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
|
|
else
|
|
pcmd->UserCallback(cmd_list, pcmd);
|
|
}
|
|
else
|
|
{
|
|
// Apply scissor/clipping rectangle
|
|
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)};
|
|
ctx->RSSetScissorRects(1, &r);
|
|
|
|
// Bind texture, Draw
|
|
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->TextureId;
|
|
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
|
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
|
}
|
|
}
|
|
global_idx_offset += cmd_list->IdxBuffer.Size;
|
|
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
|
}
|
|
|
|
// Restore modified DX state
|
|
ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
|
|
ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
|
|
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->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->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();
|
|
}
|
|
|
|
static void ImGui_ImplDX10_CreateFontsTexture()
|
|
{
|
|
// Build texture atlas
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
unsigned char* pixels;
|
|
int width, height;
|
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
|
|
|
// Upload texture to graphics system
|
|
{
|
|
D3D10_TEXTURE2D_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.Width = width;
|
|
desc.Height = height;
|
|
desc.MipLevels = 1;
|
|
desc.ArraySize = 1;
|
|
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
desc.SampleDesc.Count = 1;
|
|
desc.Usage = D3D10_USAGE_DEFAULT;
|
|
desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
|
|
desc.CPUAccessFlags = 0;
|
|
|
|
ID3D10Texture2D *pTexture = NULL;
|
|
D3D10_SUBRESOURCE_DATA subResource;
|
|
subResource.pSysMem = pixels;
|
|
subResource.SysMemPitch = desc.Width * 4;
|
|
subResource.SysMemSlicePitch = 0;
|
|
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
|
|
|
// Create texture view
|
|
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
|
ZeroMemory(&srv_desc, sizeof(srv_desc));
|
|
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
|
|
srv_desc.Texture2D.MipLevels = desc.MipLevels;
|
|
srv_desc.Texture2D.MostDetailedMip = 0;
|
|
g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView);
|
|
pTexture->Release();
|
|
}
|
|
|
|
// Store our identifier
|
|
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
|
|
|
// Create texture sampler
|
|
{
|
|
D3D10_SAMPLER_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
|
|
desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
|
|
desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
|
|
desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
|
|
desc.MipLODBias = 0.f;
|
|
desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
|
|
desc.MinLOD = 0.f;
|
|
desc.MaxLOD = 0.f;
|
|
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
|
}
|
|
}
|
|
|
|
bool ImGui_ImplDX10_CreateDeviceObjects()
|
|
{
|
|
if (!g_pd3dDevice)
|
|
return false;
|
|
if (g_pFontSampler)
|
|
ImGui_ImplDX10_InvalidateDeviceObjects();
|
|
|
|
// By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
|
|
// If you would like to use this DX10 sample code but remove this dependency you can:
|
|
// 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
|
|
// 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
|
|
// See https://github.com/ocornut/imgui/pull/638 for sources and details.
|
|
|
|
#ifdef USE_D3DCOMPILE
|
|
decltype(D3DCompile)* D3DCompile = load_d3dcompile();
|
|
if (D3DCompile == nullptr)
|
|
return false;
|
|
#endif
|
|
|
|
// Create the vertex shader
|
|
{
|
|
#ifdef USE_D3DCOMPILE
|
|
static const char* vertexShader =
|
|
"cbuffer vertexBuffer : register(b0) \
|
|
{\
|
|
float4x4 ProjectionMatrix; \
|
|
};\
|
|
struct VS_INPUT\
|
|
{\
|
|
float2 pos : POSITION;\
|
|
float4 col : COLOR0;\
|
|
float2 uv : TEXCOORD0;\
|
|
};\
|
|
\
|
|
struct PS_INPUT\
|
|
{\
|
|
float4 pos : SV_POSITION;\
|
|
float4 col : COLOR0;\
|
|
float2 uv : TEXCOORD0;\
|
|
};\
|
|
\
|
|
PS_INPUT main(VS_INPUT input)\
|
|
{\
|
|
PS_INPUT output;\
|
|
output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
|
|
output.col = input.col;\
|
|
output.uv = input.uv;\
|
|
return output;\
|
|
}";
|
|
|
|
D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &g_pVertexShaderBlob, NULL);
|
|
|
|
if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
|
return false;
|
|
|
|
if (g_pd3dDevice->CreateVertexShader((DWORD*)g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pVertexShader) != S_OK)
|
|
return false;
|
|
#else
|
|
if (g_pd3dDevice->CreateVertexShader(ImGui_vertexShaderDX10, ImGui_vertexShaderDX10_len, &g_pVertexShader) != S_OK)
|
|
return false;
|
|
#endif
|
|
|
|
// Create the input layout
|
|
D3D10_INPUT_ELEMENT_DESC local_layout[] =
|
|
{
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
|
};
|
|
#ifdef USE_D3DCOMPILE
|
|
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK)
|
|
return false;
|
|
#else
|
|
if (g_pd3dDevice->CreateInputLayout(local_layout, 3, ImGui_vertexShaderDX10, ImGui_vertexShaderDX10_len, &g_pInputLayout) != S_OK)
|
|
return false;
|
|
#endif
|
|
|
|
// Create the constant buffer
|
|
{
|
|
D3D10_BUFFER_DESC desc;
|
|
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
|
desc.Usage = D3D10_USAGE_DYNAMIC;
|
|
desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
|
|
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
|
desc.MiscFlags = 0;
|
|
g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer);
|
|
}
|
|
}
|
|
|
|
// Create the pixel shader
|
|
{
|
|
#ifdef USE_D3DCOMPILE
|
|
static const char* pixelShader =
|
|
"struct PS_INPUT\
|
|
{\
|
|
float4 pos : SV_POSITION;\
|
|
float4 col : COLOR0;\
|
|
float2 uv : TEXCOORD0;\
|
|
};\
|
|
sampler sampler0;\
|
|
Texture2D texture0;\
|
|
\
|
|
float4 main(PS_INPUT input) : SV_Target\
|
|
{\
|
|
float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
|
|
return out_col; \
|
|
}";
|
|
|
|
D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &g_pPixelShaderBlob, NULL);
|
|
|
|
if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
|
|
return false;
|
|
if (g_pd3dDevice->CreatePixelShader((DWORD*)g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize(), &g_pPixelShader) != S_OK)
|
|
return false;
|
|
#else
|
|
if (g_pd3dDevice->CreatePixelShader(ImGui_pixelShaderDX10, ImGui_pixelShaderDX10_len, &g_pPixelShader) != S_OK)
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#ifdef USE_D3DCOMPILE
|
|
unload_d3dcompile();
|
|
#endif
|
|
|
|
// Create the blending setup
|
|
{
|
|
D3D10_BLEND_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.AlphaToCoverageEnable = false;
|
|
desc.BlendEnable[0] = true;
|
|
desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
|
|
desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
|
|
desc.BlendOp = D3D10_BLEND_OP_ADD;
|
|
desc.SrcBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
|
|
desc.DestBlendAlpha = D3D10_BLEND_ZERO;
|
|
desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
|
|
desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
|
|
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
|
}
|
|
|
|
// Create the rasterizer state
|
|
{
|
|
D3D10_RASTERIZER_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.FillMode = D3D10_FILL_SOLID;
|
|
desc.CullMode = D3D10_CULL_NONE;
|
|
desc.ScissorEnable = true;
|
|
desc.DepthClipEnable = true;
|
|
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
|
}
|
|
|
|
// Create depth-stencil State
|
|
{
|
|
D3D10_DEPTH_STENCIL_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.DepthEnable = false;
|
|
desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
|
|
desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
|
|
desc.StencilEnable = false;
|
|
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
|
|
desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
|
|
desc.BackFace = desc.FrontFace;
|
|
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
|
}
|
|
|
|
ImGui_ImplDX10_CreateFontsTexture();
|
|
|
|
return true;
|
|
}
|
|
|
|
void ImGui_ImplDX10_InvalidateDeviceObjects()
|
|
{
|
|
if (!g_pd3dDevice)
|
|
return;
|
|
|
|
if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; }
|
|
if (g_pFontTextureView) { g_pFontTextureView->Release(); g_pFontTextureView = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
|
|
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
|
|
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
|
|
|
|
if (g_pBlendState) { g_pBlendState->Release(); g_pBlendState = NULL; }
|
|
if (g_pDepthStencilState) { g_pDepthStencilState->Release(); g_pDepthStencilState = NULL; }
|
|
if (g_pRasterizerState) { g_pRasterizerState->Release(); g_pRasterizerState = NULL; }
|
|
if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; }
|
|
if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; }
|
|
if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; }
|
|
if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; }
|
|
#ifdef USE_D3DCOMPILE
|
|
if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; }
|
|
if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; }
|
|
#endif
|
|
}
|
|
|
|
bool ImGui_ImplDX10_Init(ID3D10Device* device)
|
|
{
|
|
// Setup back-end capabilities flags
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
io.BackendRendererName = "imgui_impl_dx10";
|
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
|
|
|
// Get factory from device
|
|
IDXGIDevice* pDXGIDevice = NULL;
|
|
IDXGIAdapter* pDXGIAdapter = NULL;
|
|
IDXGIFactory* pFactory = NULL;
|
|
|
|
if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
|
|
if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
|
|
if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
|
|
{
|
|
g_pd3dDevice = device;
|
|
g_pFactory = pFactory;
|
|
}
|
|
if (pDXGIDevice) pDXGIDevice->Release();
|
|
if (pDXGIAdapter) pDXGIAdapter->Release();
|
|
g_pd3dDevice->AddRef();
|
|
|
|
return true;
|
|
}
|
|
|
|
void ImGui_ImplDX10_Shutdown()
|
|
{
|
|
ImGui_ImplDX10_InvalidateDeviceObjects();
|
|
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
|
|
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
|
}
|
|
|
|
void ImGui_ImplDX10_NewFrame()
|
|
{
|
|
if (!g_pFontSampler)
|
|
ImGui_ImplDX10_CreateDeviceObjects();
|
|
}
|