mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Implement ImGui.
This commit is contained in:
parent
dabda369ca
commit
05e09ba7e2
16 changed files with 361 additions and 23 deletions
|
|
@ -43,6 +43,7 @@ set(SWA_CPU_CXX_SOURCES
|
|||
|
||||
set(SWA_GPU_CXX_SOURCES
|
||||
"gpu/video.cpp"
|
||||
"gpu/imgui_snapshot.cpp"
|
||||
"gpu/rhi/rt64_d3d12.cpp"
|
||||
"gpu/rhi/rt64_vulkan.cpp"
|
||||
)
|
||||
|
|
@ -111,6 +112,7 @@ find_package(directx-dxc REQUIRED)
|
|||
find_package(zstd CONFIG REQUIRED)
|
||||
find_package(Stb REQUIRED)
|
||||
find_package(unofficial-concurrentqueue REQUIRED)
|
||||
find_package(imgui CONFIG REQUIRED)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/D3D12)
|
||||
add_custom_command(TARGET UnleashedRecomp POST_BUILD
|
||||
|
|
@ -142,6 +144,7 @@ target_link_libraries(UnleashedRecomp PRIVATE
|
|||
zstd::libzstd_static
|
||||
unofficial::concurrentqueue::concurrentqueue
|
||||
Synchronization
|
||||
imgui::imgui
|
||||
)
|
||||
|
||||
target_include_directories(UnleashedRecomp PRIVATE
|
||||
|
|
@ -178,6 +181,8 @@ function(compile_pixel_shader FILE_PATH)
|
|||
endfunction()
|
||||
|
||||
compile_vertex_shader(copy_vs)
|
||||
compile_pixel_shader(imgui_ps)
|
||||
compile_vertex_shader(imgui_vs)
|
||||
compile_pixel_shader(movie_ps)
|
||||
compile_vertex_shader(movie_vs)
|
||||
compile_pixel_shader(resolve_msaa_depth_2x)
|
||||
|
|
|
|||
54
UnleashedRecomp/gpu/imgui_snapshot.cpp
Normal file
54
UnleashedRecomp/gpu/imgui_snapshot.cpp
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#include "imgui_snapshot.h"
|
||||
|
||||
void ImDrawDataSnapshot::Clear()
|
||||
{
|
||||
for (int n = 0; n < Cache.GetMapSize(); n++)
|
||||
if (ImDrawDataSnapshotEntry* entry = Cache.TryGetMapData(n))
|
||||
IM_DELETE(entry->OurCopy);
|
||||
Cache.Clear();
|
||||
DrawData.Clear();
|
||||
}
|
||||
|
||||
void ImDrawDataSnapshot::SnapUsingSwap(ImDrawData* src, double current_time)
|
||||
{
|
||||
ImDrawData* dst = &DrawData;
|
||||
IM_ASSERT(src != dst && src->Valid);
|
||||
|
||||
// Copy all fields except CmdLists[]
|
||||
ImVector<ImDrawList*> backup_draw_list;
|
||||
backup_draw_list.swap(src->CmdLists);
|
||||
IM_ASSERT(src->CmdLists.Data == NULL);
|
||||
*dst = *src;
|
||||
backup_draw_list.swap(src->CmdLists);
|
||||
|
||||
// Swap and mark as used
|
||||
for (ImDrawList* src_list : src->CmdLists)
|
||||
{
|
||||
ImDrawDataSnapshotEntry* entry = GetOrAddEntry(src_list);
|
||||
if (entry->OurCopy == NULL)
|
||||
{
|
||||
entry->SrcCopy = src_list;
|
||||
entry->OurCopy = IM_NEW(ImDrawList)(src_list->_Data);
|
||||
}
|
||||
IM_ASSERT(entry->SrcCopy == src_list);
|
||||
entry->SrcCopy->CmdBuffer.swap(entry->OurCopy->CmdBuffer); // Cheap swap
|
||||
entry->SrcCopy->IdxBuffer.swap(entry->OurCopy->IdxBuffer);
|
||||
entry->SrcCopy->VtxBuffer.swap(entry->OurCopy->VtxBuffer);
|
||||
entry->SrcCopy->CmdBuffer.reserve(entry->OurCopy->CmdBuffer.Capacity); // Preserve bigger size to avoid reallocs for two consecutive frames
|
||||
entry->SrcCopy->IdxBuffer.reserve(entry->OurCopy->IdxBuffer.Capacity);
|
||||
entry->SrcCopy->VtxBuffer.reserve(entry->OurCopy->VtxBuffer.Capacity);
|
||||
entry->LastUsedTime = current_time;
|
||||
dst->CmdLists.push_back(entry->OurCopy);
|
||||
}
|
||||
|
||||
// Cleanup unused data
|
||||
const double gc_threshold = current_time - MemoryCompactTimer;
|
||||
for (int n = 0; n < Cache.GetMapSize(); n++)
|
||||
if (ImDrawDataSnapshotEntry* entry = Cache.TryGetMapData(n))
|
||||
{
|
||||
if (entry->LastUsedTime > gc_threshold)
|
||||
continue;
|
||||
IM_DELETE(entry->OurCopy);
|
||||
Cache.Remove(GetDrawListID(entry->SrcCopy), entry);
|
||||
}
|
||||
};
|
||||
32
UnleashedRecomp/gpu/imgui_snapshot.h
Normal file
32
UnleashedRecomp/gpu/imgui_snapshot.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
// https://github.com/ocornut/imgui/issues/1860#issuecomment-1927630727
|
||||
|
||||
// Usage:
|
||||
// static ImDrawDataSnapshot snapshot; // Important: make persistent accross frames to reuse buffers.
|
||||
// snapshot.SnapUsingSwap(ImGui::GetDrawData(), ImGui::GetTime());
|
||||
// [...]
|
||||
// ImGui_ImplDX11_RenderDrawData(&snapshot.DrawData);
|
||||
|
||||
struct ImDrawDataSnapshotEntry
|
||||
{
|
||||
ImDrawList* SrcCopy = NULL;
|
||||
ImDrawList* OurCopy = NULL;
|
||||
double LastUsedTime = 0.0;
|
||||
};
|
||||
|
||||
struct ImDrawDataSnapshot
|
||||
{
|
||||
// Members
|
||||
ImDrawData DrawData;
|
||||
ImPool<ImDrawDataSnapshotEntry> Cache;
|
||||
float MemoryCompactTimer = 20.0f; // Discard unused data after 20 seconds
|
||||
|
||||
~ImDrawDataSnapshot() { Clear(); }
|
||||
void Clear();
|
||||
void SnapUsingSwap(ImDrawData* src, double current_time); // Efficient snapshot by swapping data, meaning "src_list" is unusable.
|
||||
|
||||
// Internals
|
||||
ImGuiID GetDrawListID(ImDrawList* src_list) { return ImHashData(&src_list, sizeof(src_list)); } // Hash pointer
|
||||
ImDrawDataSnapshotEntry* GetOrAddEntry(ImDrawList* src_list) { return Cache.GetOrAddByKey(GetDrawListID(src_list)); }
|
||||
};
|
||||
|
|
@ -1265,7 +1265,7 @@ namespace RT64 {
|
|||
float mipLODBias = 0.0f;
|
||||
uint32_t maxAnisotropy = 16;
|
||||
bool anisotropyEnabled = false;
|
||||
RenderComparisonFunction comparisonFunc = RenderComparisonFunction::LESS_EQUAL;
|
||||
RenderComparisonFunction comparisonFunc = RenderComparisonFunction::NEVER;
|
||||
bool comparisonEnabled = false;
|
||||
RenderBorderColor borderColor = RenderBorderColor::OPAQUE_BLACK;
|
||||
float minLOD = 0.0f;
|
||||
|
|
|
|||
18
UnleashedRecomp/gpu/shader/imgui_common.hlsli
Normal file
18
UnleashedRecomp/gpu/shader/imgui_common.hlsli
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
uint Texture2DDescriptorIndex;
|
||||
float2 InverseDisplaySize;
|
||||
};
|
||||
|
||||
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
|
||||
SamplerState g_SamplerDescriptorHeap[] : register(s0, space1);
|
||||
[[vk::push_constant]] ConstantBuffer<PushConstants> g_PushConstants : register(b0, space2);
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 UV : TEXCOORD;
|
||||
float4 Color : COLOR;
|
||||
};
|
||||
11
UnleashedRecomp/gpu/shader/imgui_ps.hlsl
Normal file
11
UnleashedRecomp/gpu/shader/imgui_ps.hlsl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include "imgui_common.hlsli"
|
||||
|
||||
float4 main(in Interpolators interpolators) : SV_Target
|
||||
{
|
||||
float4 color = interpolators.Color;
|
||||
|
||||
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
||||
color *= g_Texture2DDescriptorHeap[g_PushConstants.Texture2DDescriptorIndex].Sample(g_SamplerDescriptorHeap[0], interpolators.UV);
|
||||
|
||||
return color;
|
||||
}
|
||||
8
UnleashedRecomp/gpu/shader/imgui_vs.hlsl
Normal file
8
UnleashedRecomp/gpu/shader/imgui_vs.hlsl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include "imgui_common.hlsli"
|
||||
|
||||
void main(in float2 position : POSITION, in float2 uv : TEXCOORD, in float4 color : COLOR, out Interpolators interpolators)
|
||||
{
|
||||
interpolators.Position = float4(position * g_PushConstants.InverseDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
||||
interpolators.UV = uv;
|
||||
interpolators.Color = color;
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.hlsli"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "movie_common.hlsl"
|
||||
#include "movie_common.hlsli"
|
||||
|
||||
PixelShaderOutput main(in Interpolators In)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "movie_common.hlsl"
|
||||
#include "movie_common.hlsli"
|
||||
|
||||
Interpolators main(in VertexShaderInput In)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
uint ResourceDescriptorIndex;
|
||||
|
|
|
|||
|
|
@ -8,12 +8,17 @@
|
|||
#include <xxHashMap.h>
|
||||
#include <shader/shader_cache.h>
|
||||
|
||||
#include "imgui_snapshot.h"
|
||||
#include "gpu/video.h"
|
||||
#include "ui/window.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "shader/copy_vs.hlsl.dxil.h"
|
||||
#include "shader/copy_vs.hlsl.spirv.h"
|
||||
#include "shader/imgui_ps.hlsl.dxil.h"
|
||||
#include "shader/imgui_ps.hlsl.spirv.h"
|
||||
#include "shader/imgui_vs.hlsl.dxil.h"
|
||||
#include "shader/imgui_vs.hlsl.spirv.h"
|
||||
#include "shader/movie_vs.hlsl.dxil.h"
|
||||
#include "shader/movie_vs.hlsl.spirv.h"
|
||||
#include "shader/movie_ps.hlsl.dxil.h"
|
||||
|
|
@ -516,6 +521,7 @@ enum class RenderCommandType
|
|||
UnlockTextureRect,
|
||||
UnlockBuffer16,
|
||||
UnlockBuffer32,
|
||||
DrawImGui,
|
||||
Present,
|
||||
StretchRect,
|
||||
SetRenderTarget,
|
||||
|
|
@ -952,11 +958,146 @@ static bool DetectWine()
|
|||
return dllHandle != nullptr && GetProcAddress(dllHandle, "wine_get_version") != nullptr;
|
||||
}
|
||||
|
||||
static constexpr size_t TEXTURE_DESCRIPTOR_SIZE = 65536;
|
||||
static constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024;
|
||||
|
||||
static std::unique_ptr<RenderTexture> g_imFontTexture;
|
||||
static std::unique_ptr<RenderTextureView> g_imFontTextureView;
|
||||
static uint32_t g_imFontTextureDescriptorIndex;
|
||||
static bool g_imPendingBarrier = true;
|
||||
static std::unique_ptr<RenderPipelineLayout> g_imPipelineLayout;
|
||||
static std::unique_ptr<RenderPipeline> g_imPipeline;
|
||||
static ImDrawDataSnapshot g_imSnapshot;
|
||||
|
||||
template<typename T>
|
||||
static void ExecuteCopyCommandList(const T& function)
|
||||
{
|
||||
std::lock_guard lock(g_copyMutex);
|
||||
|
||||
g_copyCommandList->begin();
|
||||
function();
|
||||
g_copyCommandList->end();
|
||||
g_copyQueue->executeCommandLists(g_copyCommandList.get(), g_copyCommandFence.get());
|
||||
g_copyQueue->waitForCommandFence(g_copyCommandFence.get());
|
||||
}
|
||||
|
||||
static constexpr uint32_t PITCH_ALIGNMENT = 0x100;
|
||||
static constexpr uint32_t PLACEMENT_ALIGNMENT = 0x200;
|
||||
|
||||
static void CreateImGuiBackend()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
|
||||
ImGui_ImplSDL2_InitForOther(Window::s_pWindow);
|
||||
|
||||
uint8_t* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
|
||||
|
||||
RenderTextureDesc textureDesc;
|
||||
textureDesc.dimension = RenderTextureDimension::TEXTURE_2D;
|
||||
textureDesc.width = width;
|
||||
textureDesc.height = height;
|
||||
textureDesc.depth = 1;
|
||||
textureDesc.mipLevels = 1;
|
||||
textureDesc.arraySize = 1;
|
||||
textureDesc.format = RenderFormat::R8_UNORM;
|
||||
g_imFontTexture = g_device->createTexture(textureDesc);
|
||||
|
||||
uint32_t rowPitch = (width + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
|
||||
uint32_t slicePitch = (rowPitch * height + PLACEMENT_ALIGNMENT - 1) & ~(PLACEMENT_ALIGNMENT - 1);
|
||||
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(slicePitch));
|
||||
uint8_t* mappedMemory = reinterpret_cast<uint8_t*>(uploadBuffer->map());
|
||||
|
||||
if (rowPitch == width)
|
||||
{
|
||||
memcpy(mappedMemory, pixels, slicePitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(mappedMemory, pixels, width);
|
||||
pixels += width;
|
||||
mappedMemory += rowPitch;
|
||||
}
|
||||
}
|
||||
|
||||
uploadBuffer->unmap();
|
||||
|
||||
ExecuteCopyCommandList([&]
|
||||
{
|
||||
g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(g_imFontTexture.get(), RenderTextureLayout::COPY_DEST));
|
||||
|
||||
g_copyCommandList->copyTextureRegion(
|
||||
RenderTextureCopyLocation::Subresource(g_imFontTexture.get(), 0),
|
||||
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), RenderFormat::R8_UNORM, width, height, 1, rowPitch, 0));
|
||||
});
|
||||
|
||||
RenderTextureViewDesc textureViewDesc;
|
||||
textureViewDesc.format = textureDesc.format;
|
||||
textureViewDesc.dimension = RenderTextureViewDimension::TEXTURE_2D;
|
||||
textureViewDesc.mipLevels = 1;
|
||||
textureViewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::ONE, RenderSwizzle::ONE, RenderSwizzle::ONE, RenderSwizzle::R);
|
||||
g_imFontTextureView = g_imFontTexture->createTextureView(textureViewDesc);
|
||||
|
||||
g_imFontTextureDescriptorIndex = g_textureDescriptorAllocator.allocate();
|
||||
g_textureDescriptorSet->setTexture(g_imFontTextureDescriptorIndex, g_imFontTexture.get(), RenderTextureLayout::SHADER_READ, g_imFontTextureView.get());
|
||||
|
||||
io.Fonts->SetTexID(ImTextureID(g_imFontTextureDescriptorIndex));
|
||||
|
||||
RenderPipelineLayoutBuilder pipelineLayoutBuilder;
|
||||
pipelineLayoutBuilder.begin(false, true);
|
||||
|
||||
RenderDescriptorSetBuilder descriptorSetBuilder;
|
||||
descriptorSetBuilder.begin();
|
||||
descriptorSetBuilder.addTexture(0, TEXTURE_DESCRIPTOR_SIZE);
|
||||
descriptorSetBuilder.end(true, TEXTURE_DESCRIPTOR_SIZE);
|
||||
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
|
||||
|
||||
descriptorSetBuilder.begin();
|
||||
descriptorSetBuilder.addSampler(0, SAMPLER_DESCRIPTOR_SIZE);
|
||||
descriptorSetBuilder.end(true, SAMPLER_DESCRIPTOR_SIZE);
|
||||
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
|
||||
|
||||
pipelineLayoutBuilder.addPushConstant(0, 2, 12, RenderShaderStageFlag::VERTEX | RenderShaderStageFlag::PIXEL);
|
||||
|
||||
pipelineLayoutBuilder.end();
|
||||
g_imPipelineLayout = pipelineLayoutBuilder.create(g_device.get());
|
||||
|
||||
auto vertexShader = CREATE_SHADER(imgui_vs);
|
||||
auto pixelShader = CREATE_SHADER(imgui_ps);
|
||||
|
||||
RenderInputElement inputElements[3];
|
||||
inputElements[0] = RenderInputElement("POSITION", 0, 0, RenderFormat::R32G32_FLOAT, 0, offsetof(ImDrawVert, pos));
|
||||
inputElements[1] = RenderInputElement("TEXCOORD", 0, 1, RenderFormat::R32G32_FLOAT, 0, offsetof(ImDrawVert, uv));
|
||||
inputElements[2] = RenderInputElement("COLOR", 0, 2, RenderFormat::R8G8B8A8_UNORM, 0, offsetof(ImDrawVert, col));
|
||||
|
||||
RenderInputSlot inputSlot(0, sizeof(ImDrawVert));
|
||||
|
||||
RenderGraphicsPipelineDesc pipelineDesc;
|
||||
pipelineDesc.pipelineLayout = g_imPipelineLayout.get();
|
||||
pipelineDesc.vertexShader = vertexShader.get();
|
||||
pipelineDesc.pixelShader = pixelShader.get();
|
||||
pipelineDesc.renderTargetFormat[0] = RenderFormat::B8G8R8A8_UNORM;
|
||||
pipelineDesc.renderTargetBlend[0] = RenderBlendDesc::AlphaBlend();
|
||||
pipelineDesc.renderTargetCount = 1;
|
||||
pipelineDesc.inputElements = inputElements;
|
||||
pipelineDesc.inputElementsCount = std::size(inputElements);
|
||||
pipelineDesc.inputSlots = &inputSlot;
|
||||
pipelineDesc.inputSlotsCount = 1;
|
||||
g_imPipeline = g_device->createGraphicsPipeline(pipelineDesc);
|
||||
}
|
||||
|
||||
static void CreateHostDevice()
|
||||
{
|
||||
for (uint32_t i = 0; i < 16; i++)
|
||||
g_inputSlots[i].index = i;
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
|
||||
Window::Init();
|
||||
|
||||
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
|
||||
|
|
@ -994,9 +1135,6 @@ static void CreateHostDevice()
|
|||
|
||||
RenderPipelineLayoutBuilder pipelineLayoutBuilder;
|
||||
pipelineLayoutBuilder.begin(false, true);
|
||||
|
||||
constexpr size_t TEXTURE_DESCRIPTOR_SIZE = 65536;
|
||||
constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024;
|
||||
|
||||
RenderDescriptorSetBuilder descriptorSetBuilder;
|
||||
descriptorSetBuilder.begin();
|
||||
|
|
@ -1113,6 +1251,8 @@ static void CreateHostDevice()
|
|||
desc.depthTargetFormat = RenderFormat::D32_FLOAT;
|
||||
g_resolveMsaaDepthPipelines[i] = g_device->createGraphicsPipeline(desc);
|
||||
}
|
||||
|
||||
CreateImGuiBackend();
|
||||
}
|
||||
|
||||
static void WaitForGPU()
|
||||
|
|
@ -1252,9 +1392,6 @@ static void ProcDestructResource(const RenderCommand& cmd)
|
|||
g_tempResources[g_frame].push_back(args.resource);
|
||||
}
|
||||
|
||||
static constexpr uint32_t PITCH_ALIGNMENT = 0x100;
|
||||
static constexpr uint32_t PLACEMENT_ALIGNMENT = 0x200;
|
||||
|
||||
static uint32_t ComputeTexturePitch(GuestTexture* texture)
|
||||
{
|
||||
return (texture->width * RenderFormatSize(texture->format) + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
|
||||
|
|
@ -1313,18 +1450,6 @@ static void* LockVertexBuffer(GuestBuffer* buffer, uint32_t, uint32_t, uint32_t
|
|||
return LockBuffer(buffer, flags);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void ExecuteCopyCommandList(const T& function)
|
||||
{
|
||||
std::lock_guard lock(g_copyMutex);
|
||||
|
||||
g_copyCommandList->begin();
|
||||
function();
|
||||
g_copyCommandList->end();
|
||||
g_copyQueue->executeCommandLists(g_copyCommandList.get(), g_copyCommandFence.get());
|
||||
g_copyQueue->waitForCommandFence(g_copyCommandFence.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue)
|
||||
{
|
||||
|
|
@ -1434,9 +1559,79 @@ static uint32_t HashVertexDeclaration(uint32_t vertexDeclaration)
|
|||
return vertexDeclaration;
|
||||
}
|
||||
|
||||
static void DrawImGui()
|
||||
{
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
// ImGui logic here
|
||||
ImGui::Render();
|
||||
|
||||
auto drawData = ImGui::GetDrawData();
|
||||
if (drawData->CmdListsCount != 0)
|
||||
{
|
||||
g_imSnapshot.SnapUsingSwap(drawData, ImGui::GetTime());
|
||||
|
||||
RenderCommand cmd;
|
||||
cmd.type = RenderCommandType::DrawImGui;
|
||||
g_renderQueue.enqueue(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcDrawImGui(const RenderCommand& cmd)
|
||||
{
|
||||
auto& commandList = g_commandLists[g_frame];
|
||||
|
||||
if (g_imPendingBarrier)
|
||||
{
|
||||
commandList->barriers(RenderBarrierStage::GRAPHICS, RenderTextureBarrier(g_imFontTexture.get(), RenderTextureLayout::SHADER_READ));
|
||||
g_imPendingBarrier = false;
|
||||
}
|
||||
|
||||
commandList->setGraphicsPipelineLayout(g_imPipelineLayout.get());
|
||||
commandList->setPipeline(g_imPipeline.get());
|
||||
commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 0);
|
||||
commandList->setGraphicsDescriptorSet(g_samplerDescriptorSet.get(), 1);
|
||||
|
||||
auto& drawData = g_imSnapshot.DrawData;
|
||||
commandList->setViewports(RenderViewport(drawData.DisplayPos.x, drawData.DisplayPos.y, drawData.DisplaySize.x, drawData.DisplaySize.y));
|
||||
|
||||
float inverseDisplaySize[] = { 1.0f / drawData.DisplaySize.x, 1.0f / drawData.DisplaySize.y };
|
||||
commandList->setGraphicsPushConstants(0, inverseDisplaySize, 4, 8);
|
||||
|
||||
for (int i = 0; i < drawData.CmdListsCount; i++)
|
||||
{
|
||||
auto& drawList = drawData.CmdLists[i];
|
||||
|
||||
auto vertexBufferAllocation = g_uploadAllocators[g_frame].allocate<false>(drawList->VtxBuffer.Data, drawList->VtxBuffer.Size * sizeof(ImDrawVert), alignof(ImDrawVert));
|
||||
auto indexBufferAllocation = g_uploadAllocators[g_frame].allocate<false>(drawList->IdxBuffer.Data, drawList->IdxBuffer.Size * sizeof(uint16_t), alignof(uint16_t));
|
||||
|
||||
const RenderVertexBufferView vertexBufferView(vertexBufferAllocation.buffer->at(vertexBufferAllocation.offset), drawList->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||
const RenderInputSlot inputSlot(0, sizeof(ImDrawVert));
|
||||
commandList->setVertexBuffers(0, &vertexBufferView, 1, &inputSlot);
|
||||
|
||||
const RenderIndexBufferView indexBufferView(indexBufferAllocation.buffer->at(indexBufferAllocation.offset), drawList->IdxBuffer.Size * sizeof(uint16_t), RenderFormat::R16_UINT);
|
||||
commandList->setIndexBuffer(&indexBufferView);
|
||||
|
||||
for (int j = 0; j < drawList->CmdBuffer.Size; j++)
|
||||
{
|
||||
auto& drawCmd = drawList->CmdBuffer[j];
|
||||
|
||||
if (drawCmd.ClipRect.z <= drawCmd.ClipRect.x || drawCmd.ClipRect.w <= drawCmd.ClipRect.y)
|
||||
continue;
|
||||
|
||||
uint32_t descriptorIndex = uint32_t(drawCmd.GetTexID());
|
||||
commandList->setGraphicsPushConstants(0, &descriptorIndex, 0, 4);
|
||||
commandList->setScissors(RenderRect(int32_t(drawCmd.ClipRect.x), int32_t(drawCmd.ClipRect.y), int32_t(drawCmd.ClipRect.z), int32_t(drawCmd.ClipRect.w)));
|
||||
commandList->drawIndexedInstanced(drawCmd.ElemCount, 1, drawCmd.IdxOffset, drawCmd.VtxOffset, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Present()
|
||||
{
|
||||
DrawImGui();
|
||||
WaitForRenderThread();
|
||||
|
||||
g_pendingRenderThread = true;
|
||||
|
||||
RenderCommand cmd;
|
||||
|
|
@ -2954,6 +3149,7 @@ static std::thread g_renderThread([]
|
|||
case RenderCommandType::UnlockTextureRect: ProcUnlockTextureRect(cmd); break;
|
||||
case RenderCommandType::UnlockBuffer16: ProcUnlockBuffer16(cmd); break;
|
||||
case RenderCommandType::UnlockBuffer32: ProcUnlockBuffer32(cmd); break;
|
||||
case RenderCommandType::DrawImGui: ProcDrawImGui(cmd); break;
|
||||
case RenderCommandType::Present: ProcPresent(cmd); break;
|
||||
case RenderCommandType::StretchRect: ProcStretchRect(cmd); break;
|
||||
case RenderCommandType::SetRenderTarget: ProcSetRenderTarget(cmd); break;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
#include <zstd.h>
|
||||
#include <stb_image.h>
|
||||
#include <concurrentqueue/blockingconcurrentqueue.h>
|
||||
#include <SDL.h>
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <imgui_impl_sdl2.h>
|
||||
|
||||
#include "framework.h"
|
||||
#include "mutex.h"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ bool m_isFullscreenKeyReleased = true;
|
|||
|
||||
int Window_OnSDLEvent(void*, SDL_Event* event)
|
||||
{
|
||||
if (ImGui::GetIO().BackendPlatformUserData != nullptr)
|
||||
ImGui_ImplSDL2_ProcessEvent(event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
#include "res/icon.h"
|
||||
#include "ui/window_events.h"
|
||||
#include "config.h"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
"tomlplusplus",
|
||||
"zstd",
|
||||
"stb",
|
||||
"concurrentqueue"
|
||||
"concurrentqueue",
|
||||
{
|
||||
"name": "imgui",
|
||||
"features": [ "sdl2-binding" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue