diff --git a/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12.h b/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12.h index cddad638..11e57a16 100644 --- a/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12.h +++ b/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12.h @@ -233,7 +233,7 @@ class GigiInterpreterPreviewWindowDX12 : public IGigiInterpreter } } - void ShowUI(bool minimalUI); + void ShowUI(bool minimalUI, bool paused); void OnPreCompile() override final { diff --git a/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12_UI.cpp b/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12_UI.cpp index 1dc058a0..5c34485f 100644 --- a/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12_UI.cpp +++ b/GigiViewerDX12/Interpreter/GigiInterpreterPreviewWindowDX12_UI.cpp @@ -22,7 +22,7 @@ static void ShowToolTip(const char* tooltip) ImGui::SetTooltip("%s", tooltip); } -static void ShowUI_Int(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Int(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.enumIndex != -1) { @@ -71,7 +71,7 @@ static void ShowUI_Int(const RenderGraph& renderGraph, const Variable& variable, } } -static void ShowUI_Int2(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Int2(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Drag) { @@ -107,7 +107,7 @@ static void ShowUI_Int2(const RenderGraph& renderGraph, const Variable& variable ImGui::InputInt2(variable.originalName.c_str(), (int*)storage); } -static void ShowUI_Int3(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Int3(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Drag) { @@ -143,7 +143,7 @@ static void ShowUI_Int3(const RenderGraph& renderGraph, const Variable& variable ImGui::InputInt3(variable.originalName.c_str(), (int*)storage); } -static void ShowUI_Int4(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Int4(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Drag) { @@ -179,7 +179,7 @@ static void ShowUI_Int4(const RenderGraph& renderGraph, const Variable& variable ImGui::InputInt4(variable.originalName.c_str(), (int*)storage); } -static void ShowUI_Uint(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Uint(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { unsigned int* v2 = (unsigned int*)storage; int v[] = { (int)v2[0] }; @@ -220,7 +220,7 @@ static void ShowUI_Uint(const RenderGraph& renderGraph, const Variable& variable v2[0] = v[0]; } -static void ShowUI_Uint2(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Uint2(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { unsigned int* v2 = (unsigned int*)storage; int v[] = { (int)v2[0], (int)v2[1] }; @@ -262,7 +262,7 @@ static void ShowUI_Uint2(const RenderGraph& renderGraph, const Variable& variabl v2[1] = v[1]; } -static void ShowUI_Uint3(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Uint3(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { unsigned int* v2 = (unsigned int*)storage; int v[] = { (int)v2[0], (int)v2[1], (int)v2[2] }; @@ -305,7 +305,7 @@ static void ShowUI_Uint3(const RenderGraph& renderGraph, const Variable& variabl v2[2] = v[2]; } -static void ShowUI_Uint4(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Uint4(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { unsigned int* v2 = (unsigned int*)storage; int v[] = { (int)v2[0], (int)v2[1], (int)v2[2], (int)v2[3] }; @@ -349,7 +349,7 @@ static void ShowUI_Uint4(const RenderGraph& renderGraph, const Variable& variabl v2[3] = v[3]; } -static void ShowUI_Float(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Float(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Angle) { @@ -391,7 +391,7 @@ static void ShowUI_Float(const RenderGraph& renderGraph, const Variable& variabl } } -static void ShowUI_Float2(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Float2(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Drag) { @@ -429,7 +429,7 @@ static void ShowUI_Float2(const RenderGraph& renderGraph, const Variable& variab } } -static void ShowUI_Float3(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Float3(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Color) ImGui::ColorEdit3(variable.originalName.c_str(), (float*)storage); @@ -469,7 +469,7 @@ static void ShowUI_Float3(const RenderGraph& renderGraph, const Variable& variab } } -static void ShowUI_Float4(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Float4(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { if (variable.UISettings.UIHint == VariableUIHint::Color) ImGui::ColorEdit4(variable.originalName.c_str(), (float*)storage, ImGuiColorEditFlags_AlphaPreview); @@ -509,15 +509,15 @@ static void ShowUI_Float4(const RenderGraph& renderGraph, const Variable& variab } } -static void ShowUI_Bool(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Bool(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { - if (variable.UISettings.UIHint == VariableUIHint::Button) + if (!paused && variable.UISettings.UIHint == VariableUIHint::Button) *(bool*)storage = ImGui::Button(variable.originalName.c_str()); else ImGui_Checkbox(variable.originalName.c_str(), (bool*)storage); } -static void ShowUI_Float4x4(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Float4x4(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { ImGui::Text(variable.originalName.c_str()); ImGui::InputFloat4("row 0", (float*)storage + 0); @@ -526,7 +526,7 @@ static void ShowUI_Float4x4(const RenderGraph& renderGraph, const Variable& vari ImGui::InputFloat4("row 3", (float*)storage + 12); } -static void ShowUI_Uint_16(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Uint_16(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { uint16_t* v2 = (uint16_t*)storage; int v[] = { (int)v2[0] }; @@ -567,12 +567,12 @@ static void ShowUI_Uint_16(const RenderGraph& renderGraph, const Variable& varia v2[0] = v[0]; } -static void ShowUI_Count(const RenderGraph& renderGraph, const Variable& variable, void* storage) +static void ShowUI_Count(const RenderGraph& renderGraph, const bool paused, const Variable& variable, void* storage) { // No-op. Shouldn't ever happen } -void GigiInterpreterPreviewWindowDX12::ShowUI(bool minimalUI) +void GigiInterpreterPreviewWindowDX12::ShowUI(bool minimalUI, bool paused) { // Minimal UI only shows public variables. // If there are none, and this is minimalUI, exit early so there's no variables window. @@ -702,7 +702,7 @@ void GigiInterpreterPreviewWindowDX12::ShowUI(bool minimalUI) { #include "external/df_serialize/_common.h" #define ENUM_ITEM(_NAME, _DESCRIPTION) \ - case DataFieldType::_NAME: ShowUI_##_NAME(m_renderGraph, *variable.variable, variable.storage.value); break; + case DataFieldType::_NAME: ShowUI_##_NAME(m_renderGraph, paused, *variable.variable, variable.storage.value); break; // clang-format off #include "external/df_serialize/_fillunsetdefines.h" #include "Schemas/DataFieldTypes.h" diff --git a/GigiViewerDX12/main.cpp b/GigiViewerDX12/main.cpp index 6fecd9e2..6f56f817 100644 --- a/GigiViewerDX12/main.cpp +++ b/GigiViewerDX12/main.cpp @@ -403,6 +403,7 @@ GigiInterpreterPreviewWindowDX12 g_interpreter; int g_executeTechniqueCount = 0; int g_executeTechniqueCountRemain = 0; bool g_executeTechnique = true; +bool g_techniquePaused = false; std::string g_commandLineLoadGGFileName; std::string g_runPyFileName; @@ -1152,8 +1153,11 @@ void HandleMainMenu() } else { - if (ImGui::Button(g_executeTechnique ? "Pause" : "Play")) - g_executeTechnique = !g_executeTechnique; + if (ImGui::Button(g_techniquePaused ? "Play" : "Pause")) + { + g_techniquePaused = !g_techniquePaused; + g_executeTechnique = !g_techniquePaused; + } } ImGui::SetNextItemWidth(50); @@ -3235,6 +3239,21 @@ void ShowImGuiWindows() ImGui::EndTable(); } } + if (ImGui::Button("Copy")) + { + std::ostringstream text; + for (size_t i = 0; i < runtimeData.materials.size(); ++i) + { + const auto& materialInfo = runtimeData.materials[i]; + text << i << " " << materialInfo.name; + if (!materialInfo.used) + text << " (unused)"; + text << "\n"; + + } + std::string textStr = text.str(); + SetClipboardDataEx(CF_TEXT, (void*)textStr.c_str(), (DWORD)textStr.length() + 1); + } //if (ImGui::Button("OK")) //ImGui::CloseCurrentPopup(); @@ -4670,6 +4689,39 @@ void ShowStructuredBuffer(const RenderGraph& renderGraph, unsigned char* bytes, } } +std::vector DecodeBc7(unsigned char* pixels, int width, int height) +{ + // Calculate how many blocks there are + int numBlocksX = (width + 3) / 4; + int numBlocksY = (height + 3) / 4; + int numBlocks = numBlocksX * numBlocksY; + + std::vector decodedPixels(width * height * 4, 0); + std::vector decodedBlock(64); + + for (int i = 0; i < numBlocks; ++i) + { + bc7decomp::unpack_bc7(&pixels[i * 16], (bc7decomp::color_rgba*)decodedBlock.data()); + + int blockX = i % numBlocksX; + int blockY = i / numBlocksX; + + int outY = blockY * 4; + int outX = blockX * 4; + + unsigned char* dest = &decodedPixels[(outY * width + outX) * 4]; + unsigned char* src = decodedBlock.data(); + for (int iy = 0; iy < 4; ++iy) + { + memcpy(dest, src, 16); + src += 16; + dest += width * 4; + } + } + + return decodedPixels; +} + void SaveAsPng(const char* fileName, ID3D12Resource* readbackResource, const DXGI_FORMAT_Info& formatInfo, int width, int height, int depth, int z, bool forceRGBA) { // TODO: bc7 treatment @@ -4683,34 +4735,7 @@ void SaveAsPng(const char* fileName, ID3D12Resource* readbackResource, const DXG if (formatInfo.isCompressed) { - // Calculate how many blocks there are - int numBlocksX = (width + 3) / 4; - int numBlocksY = (height + 3) / 4; - int numBlocks = numBlocksX * numBlocksY; - - std::vector decodedPixels(width * height * 4, 0); - std::vector decodedBlock(64); - - for (int i = 0; i < numBlocks; ++i) - { - bc7decomp::unpack_bc7(&pixels[i * 16], (bc7decomp::color_rgba*)decodedBlock.data()); - - int blockX = i % numBlocksX; - int blockY = i / numBlocksX; - - int outY = blockY * 4; - int outX = blockX * 4; - - unsigned char* dest = &decodedPixels[(outY * width + outX) * 4]; - unsigned char* src = decodedBlock.data(); - for (int iy = 0; iy < 4; ++iy) - { - memcpy(dest, src, 16); - src += 16; - dest += width * 4; - } - } - + std::vector decodedPixels = DecodeBc7(pixels, width, height); stbi_write_png(p.string().c_str(), width, height, 4, decodedPixels.data(), 0); } else @@ -4724,11 +4749,14 @@ void SaveAsPng(const char* fileName, ID3D12Resource* readbackResource, const DXG for (int i = 0; i < width * height; ++i) paddedPixels[i * 4 + 3] = 255; - for (int i = 0; i < width * height; ++i) + for (int y = 0; y < height; ++y) { - unsigned char* dest = &paddedPixels[i * 4]; - const unsigned char* src = &pixels[z * height * alignedPitch + i * formatInfo.channelCount]; - memcpy(dest, src, formatInfo.channelCount); + for (int x = 0; x < width; ++x) + { + unsigned char* dest = &paddedPixels[(x + y * width) * 4]; + const unsigned char* src = &pixels[z * height * alignedPitch + y * alignedPitch + x * formatInfo.channelCount]; + memcpy(dest, src, formatInfo.channelCount); + } } stbi_write_png(p.string().c_str(), width, height, 4, paddedPixels.data(), 0); @@ -4767,33 +4795,7 @@ void SaveImageAsCSV(const char* fileName, ID3D12Resource* readbackResource, cons std::vector decodedPixels(width * height * 4, 0); if (formatInfo.isCompressed) { - // Calculate how many blocks there are - int numBlocksX = (width + 3) / 4; - int numBlocksY = (height + 3) / 4; - int numBlocks = numBlocksX * numBlocksY; - - // decode the pixels - std::vector decodedBlock(64); - for (int i = 0; i < numBlocks; ++i) - { - bc7decomp::unpack_bc7(&pixels[i * 16], (bc7decomp::color_rgba*)decodedBlock.data()); - - int blockX = i % numBlocksX; - int blockY = i / numBlocksX; - - int outY = blockY * 4; - int outX = blockX * 4; - - unsigned char* dest = &decodedPixels[(outY * width + outX) * 4]; - unsigned char* src = decodedBlock.data(); - for (int iy = 0; iy < 4; ++iy) - { - memcpy(dest, src, 16); - src += 16; - dest += width * 4; - } - } - + std::vector decodedPixels = DecodeBc7(pixels, width, height); pixels = decodedPixels.data(); } else @@ -4839,6 +4841,94 @@ void SaveImageAsCSV(const char* fileName, ID3D12Resource* readbackResource, cons readbackResource->Unmap(0, &writeRange); } +void CopyImageToClipBoard(ID3D12Resource* readbackResource, const DXGI_FORMAT_Info& formatInfo, int width, int height, int depth, int z) +{ + unsigned char* pixels = nullptr; + readbackResource->Map(0, nullptr, (void**)&pixels); + + constexpr uint32_t kBytesPerPixel = 4; + constexpr WORD kBitsPerPixel = 8 * kBytesPerPixel; + BITMAPV5HEADER header = { + .bV5Size = sizeof(header), + .bV5Width = width, + .bV5Height = height, + .bV5Planes = 1, + .bV5BitCount = kBitsPerPixel, + .bV5Compression = BI_BITFIELDS, + .bV5RedMask = 0x000000ff, + .bV5GreenMask = 0x0000ff00, + .bV5BlueMask = 0x00ff0000, + .bV5AlphaMask = 0xff000000, + .bV5CSType = LCS_WINDOWS_COLOR_SPACE, + }; + + HGLOBAL hglob = GlobalAlloc(GMEM_MOVEABLE, sizeof(header) + width * height * 4); + if (hglob) + { + void* buffer = GlobalLock(hglob); + if (buffer) + { + CopyMemory(buffer, &header, sizeof(header)); + + if (formatInfo.isCompressed) + { + std::vector decodedPixels = DecodeBc7(pixels, width, height); + for (int i = 0; i < height; i++) { + CopyMemory((unsigned char*)buffer + sizeof(header) + i * width * kBytesPerPixel, decodedPixels.data() + (height - 1 - i) * width * kBytesPerPixel, width * kBytesPerPixel); + } + } + else + { + int unalignedPitch = width * formatInfo.bytesPerPixel; + int alignedPitch = ALIGN((D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * formatInfo.planeCount), unalignedPitch); + + if (formatInfo.channelCount == 4) + { + for (int y = 0; y < height; ++y) + { + CopyMemory((unsigned char*)buffer + sizeof(header) + (height - 1 - y) * width * formatInfo.bytesPerPixel, &pixels[z * height * alignedPitch + y * alignedPitch], unalignedPitch); + } + } + else + { + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + unsigned char values[4] = {}; + values[3] = 255; + memcpy(values, &pixels[z * height * alignedPitch + y * alignedPitch + x * formatInfo.channelCount], formatInfo.channelCount); + CopyMemory((unsigned char*)buffer + sizeof(header) + (height - 1 - y) * width * kBytesPerPixel + x * kBytesPerPixel, values, kBytesPerPixel); + } + } + } + } + + GlobalUnlock(hglob); + } + else + { + GlobalFree(hglob); + } + + if (OpenClipboard(g_hwnd)) + { + EmptyClipboard(); + SetClipboardData(CF_DIBV5, hglob); + CloseClipboard(); + } + else + { + GlobalFree(hglob); + } + } + + D3D12_RANGE writeRange; + writeRange.Begin = 1; + writeRange.End = 0; + readbackResource->Unmap(0, &writeRange); +} + void SaveAsHDR(const char* fileName, ID3D12Resource* readbackResource, const DXGI_FORMAT_Info& formatInfo, int width, int height, int depth, int z) { std::filesystem::path p(fileName); @@ -5210,6 +5300,12 @@ void ShowResourceView() static bool forceRGBA = false; static bool saveAllVertically = false; + ImGui::SameLine(); + if (ImGui::Button("Copy Image To ClipBoard")) + { + CopyImageToClipBoard(res.m_resourceReadback, formatInfo, res.m_size[0], res.m_size[1], res.m_size[2], imageZ); + } + ImGui::SameLine(); if (ImGui::Button("Save as ...") && NFD_SaveDialog("png;csv", "", &outPath) == NFD_OKAY) { @@ -6866,7 +6962,7 @@ void RenderFrame(bool forceExecute) ShowRenderGraphWindow(); ShowResourceView(); - g_interpreter.ShowUI(g_hideUI); + g_interpreter.ShowUI(g_hideUI, g_techniquePaused); ShowLog(); diff --git a/README.md b/README.md index 00b9a3a0..f0e5263b 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ Created by Alan Wolfe **Contributors:** +Berk Emre Saribas + Chris Lewin Martin Mittring