mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator.git
synced 2024-11-27 14:08:39 +01: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.
563 lines
25 KiB
C++
563 lines
25 KiB
C++
// dear imgui: Renderer for DirectX11
|
|
// This needs to be used along with a Platform Binding (e.g. Win32)
|
|
|
|
// Implemented features:
|
|
// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' 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: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
|
// 2019-04-30: DirectX11: 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-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
|
|
// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
|
|
// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
|
|
// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
|
|
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_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: DirectX11: Disabling depth-write.
|
|
|
|
#include "../imgui.h"
|
|
#include "imgui_impl_dx11.h"
|
|
|
|
// DirectX
|
|
#include <stdio.h>
|
|
#include <d3d11.h>
|
|
|
|
#include "../../overlay_experimental/ImGui_ShaderBlobs.h"
|
|
|
|
#ifdef USE_D3DCOMPILE
|
|
static ID3DBlob* g_pVertexShaderBlob = NULL;
|
|
static ID3DBlob* g_pPixelShaderBlob = NULL;
|
|
#endif
|
|
|
|
// DirectX data
|
|
static ID3D11Device* g_pd3dDevice = NULL;
|
|
static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
|
|
static IDXGIFactory* g_pFactory = NULL;
|
|
static ID3D11Buffer* g_pVB = NULL;
|
|
static ID3D11Buffer* g_pIB = NULL;
|
|
static ID3D11VertexShader* g_pVertexShader = NULL;
|
|
static ID3D11InputLayout* g_pInputLayout = NULL;
|
|
static ID3D11Buffer* g_pVertexConstantBuffer = NULL;
|
|
static ID3D11PixelShader* g_pPixelShader = NULL;
|
|
static ID3D11SamplerState* g_pFontSampler = NULL;
|
|
static ID3D11ShaderResourceView*g_pFontTextureView = NULL;
|
|
static ID3D11RasterizerState* g_pRasterizerState = NULL;
|
|
static ID3D11BlendState* g_pBlendState = NULL;
|
|
static ID3D11DepthStencilState* g_pDepthStencilState = NULL;
|
|
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
|
|
|
|
struct VERTEX_CONSTANT_BUFFER
|
|
{
|
|
float mvp[4][4];
|
|
};
|
|
|
|
static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
|
|
{
|
|
// Setup viewport
|
|
D3D11_VIEWPORT vp;
|
|
memset(&vp, 0, sizeof(D3D11_VIEWPORT));
|
|
vp.Width = draw_data->DisplaySize.x;
|
|
vp.Height = draw_data->DisplaySize.y;
|
|
vp.MinDepth = 0.0f;
|
|
vp.MaxDepth = 1.0f;
|
|
vp.TopLeftX = vp.TopLeftY = 0;
|
|
ctx->RSSetViewports(1, &vp);
|
|
|
|
// Setup 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(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
ctx->VSSetShader(g_pVertexShader, NULL, 0);
|
|
ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer);
|
|
ctx->PSSetShader(g_pPixelShader, NULL, 0);
|
|
ctx->PSSetSamplers(0, 1, &g_pFontSampler);
|
|
|
|
// Setup blend 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_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
|
{
|
|
// Avoid rendering when minimized
|
|
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
|
return;
|
|
|
|
ID3D11DeviceContext* ctx = g_pd3dDeviceContext;
|
|
|
|
// 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;
|
|
D3D11_BUFFER_DESC desc;
|
|
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
|
desc.ByteWidth = g_VertexBufferSize * sizeof(ImDrawVert);
|
|
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
desc.MiscFlags = 0;
|
|
if (g_pd3dDevice->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;
|
|
D3D11_BUFFER_DESC desc;
|
|
memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
|
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
|
desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx);
|
|
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
|
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0)
|
|
return;
|
|
}
|
|
|
|
// Upload vertex/index data into a single contiguous GPU buffer
|
|
D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
|
|
if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
|
|
return;
|
|
if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
|
|
return;
|
|
ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
|
|
ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
|
|
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;
|
|
}
|
|
ctx->Unmap(g_pVB, 0);
|
|
ctx->Unmap(g_pIB, 0);
|
|
|
|
// 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.
|
|
{
|
|
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
|
if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
|
|
return;
|
|
VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
|
|
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));
|
|
ctx->Unmap(g_pVertexConstantBuffer, 0);
|
|
}
|
|
|
|
// Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
|
|
struct BACKUP_DX11_STATE
|
|
{
|
|
UINT ScissorRectsCount, ViewportsCount;
|
|
D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
|
|
ID3D11RasterizerState* RS;
|
|
ID3D11BlendState* BlendState;
|
|
FLOAT BlendFactor[4];
|
|
UINT SampleMask;
|
|
UINT StencilRef;
|
|
ID3D11DepthStencilState* DepthStencilState;
|
|
ID3D11ShaderResourceView* PSShaderResource;
|
|
ID3D11SamplerState* PSSampler;
|
|
ID3D11PixelShader* PS;
|
|
ID3D11VertexShader* VS;
|
|
UINT PSInstancesCount, VSInstancesCount;
|
|
ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation
|
|
D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
|
|
ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
|
|
UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
|
|
DXGI_FORMAT IndexBufferFormat;
|
|
ID3D11InputLayout* InputLayout;
|
|
};
|
|
BACKUP_DX11_STATE old;
|
|
old.ScissorRectsCount = old.ViewportsCount = D3D11_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);
|
|
old.PSInstancesCount = old.VSInstancesCount = 256;
|
|
ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
|
|
ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
|
|
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_ImplDX11_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_idx_offset = 0;
|
|
int global_vtx_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 != 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)
|
|
ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
|
|
else
|
|
pcmd->UserCallback(cmd_list, pcmd);
|
|
}
|
|
else
|
|
{
|
|
// Apply scissor/clipping rectangle
|
|
const D3D11_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
|
|
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)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, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
|
|
for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
|
|
ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
|
|
ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
|
|
for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->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_ImplDX11_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
|
|
{
|
|
D3D11_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 = D3D11_USAGE_DEFAULT;
|
|
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
desc.CPUAccessFlags = 0;
|
|
|
|
ID3D11Texture2D *pTexture = NULL;
|
|
D3D11_SUBRESOURCE_DATA subResource;
|
|
subResource.pSysMem = pixels;
|
|
subResource.SysMemPitch = desc.Width * 4;
|
|
subResource.SysMemSlicePitch = 0;
|
|
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
|
|
|
// Create texture view
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
|
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
|
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
|
g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView);
|
|
pTexture->Release();
|
|
}
|
|
|
|
// Store our identifier
|
|
io.Fonts->TexID = (ImTextureID)g_pFontTextureView;
|
|
|
|
// Create texture sampler
|
|
{
|
|
D3D11_SAMPLER_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
|
|
desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
|
|
desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
|
|
desc.MipLODBias = 0.f;
|
|
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
|
|
desc.MinLOD = 0.f;
|
|
desc.MaxLOD = 0.f;
|
|
g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler);
|
|
}
|
|
}
|
|
|
|
bool ImGui_ImplDX11_CreateDeviceObjects()
|
|
{
|
|
if (!g_pd3dDevice)
|
|
return false;
|
|
if (g_pFontSampler)
|
|
ImGui_ImplDX11_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 DX11 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(), NULL, &g_pVertexShader) != S_OK)
|
|
return false;
|
|
#else
|
|
if (g_pd3dDevice->CreateVertexShader(ImGui_vertexShaderDX11, ImGui_vertexShaderDX11_len, NULL, &g_pVertexShader) != S_OK)
|
|
return false;
|
|
#endif
|
|
|
|
// Create the input layout
|
|
D3D11_INPUT_ELEMENT_DESC local_layout[] =
|
|
{
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_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_vertexShaderDX11, ImGui_vertexShaderDX11_len, &g_pInputLayout) != S_OK)
|
|
return false;
|
|
#endif
|
|
|
|
// Create the constant buffer
|
|
{
|
|
D3D11_BUFFER_DESC desc;
|
|
desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
|
|
desc.Usage = D3D11_USAGE_DYNAMIC;
|
|
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
|
desc.CPUAccessFlags = D3D11_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(), NULL, &g_pPixelShader) != S_OK)
|
|
return false;
|
|
#else
|
|
|
|
if (g_pd3dDevice->CreatePixelShader(ImGui_pixelShaderDX11, ImGui_pixelShaderDX11_len, NULL, &g_pPixelShader) != S_OK)
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
#ifdef USE_D3DCOMPILE
|
|
unload_d3dcompile();
|
|
#endif
|
|
|
|
// Create the blending setup
|
|
{
|
|
D3D11_BLEND_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.AlphaToCoverageEnable = false;
|
|
desc.RenderTarget[0].BlendEnable = true;
|
|
desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
|
desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
|
desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
|
desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
|
desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
|
desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
|
desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
|
g_pd3dDevice->CreateBlendState(&desc, &g_pBlendState);
|
|
}
|
|
|
|
// Create the rasterizer state
|
|
{
|
|
D3D11_RASTERIZER_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.FillMode = D3D11_FILL_SOLID;
|
|
desc.CullMode = D3D11_CULL_NONE;
|
|
desc.ScissorEnable = true;
|
|
desc.DepthClipEnable = true;
|
|
g_pd3dDevice->CreateRasterizerState(&desc, &g_pRasterizerState);
|
|
}
|
|
|
|
// Create depth-stencil State
|
|
{
|
|
D3D11_DEPTH_STENCIL_DESC desc;
|
|
ZeroMemory(&desc, sizeof(desc));
|
|
desc.DepthEnable = false;
|
|
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
|
desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
|
|
desc.StencilEnable = false;
|
|
desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
|
|
desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
|
|
desc.BackFace = desc.FrontFace;
|
|
g_pd3dDevice->CreateDepthStencilState(&desc, &g_pDepthStencilState);
|
|
}
|
|
|
|
ImGui_ImplDX11_CreateFontsTexture();
|
|
|
|
return true;
|
|
}
|
|
|
|
void ImGui_ImplDX11_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_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
|
|
{
|
|
// Setup back-end capabilities flags
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
io.BackendRendererName = "imgui_impl_dx11";
|
|
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_pd3dDeviceContext = device_context;
|
|
g_pFactory = pFactory;
|
|
}
|
|
if (pDXGIDevice) pDXGIDevice->Release();
|
|
if (pDXGIAdapter) pDXGIAdapter->Release();
|
|
g_pd3dDevice->AddRef();
|
|
g_pd3dDeviceContext->AddRef();
|
|
|
|
return true;
|
|
}
|
|
|
|
void ImGui_ImplDX11_Shutdown()
|
|
{
|
|
ImGui_ImplDX11_InvalidateDeviceObjects();
|
|
if (g_pFactory) { g_pFactory->Release(); g_pFactory = NULL; }
|
|
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
|
|
if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
|
|
}
|
|
|
|
void ImGui_ImplDX11_NewFrame()
|
|
{
|
|
if (!g_pFontSampler)
|
|
ImGui_ImplDX11_CreateDeviceObjects();
|
|
}
|