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
	
	 Skyth
						Skyth