diff --git a/parts/CMakeLists.txt b/parts/CMakeLists.txt index 300120f..edb6ee1 100644 --- a/parts/CMakeLists.txt +++ b/parts/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(exd) add_subdirectory(exl) add_subdirectory(hex) add_subdirectory(mdl) +add_subdirectory(shpk) add_subdirectory(tex) \ No newline at end of file diff --git a/parts/shpk/CMakeLists.txt b/parts/shpk/CMakeLists.txt new file mode 100644 index 0000000..cf2c8fb --- /dev/null +++ b/parts/shpk/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 Joshua Goins +# SPDX-License-Identifier: CC0-1.0 + +find_package(spirv_cross_core REQUIRED) +find_package(spirv_cross_glsl REQUIRED) +find_package(SPIRV-Headers REQUIRED) + +add_library(shpkpart STATIC) +target_sources(shpkpart PRIVATE shpkpart.cpp) +target_link_libraries(shpkpart PUBLIC physis z dxbc spirv-cross-core spirv-cross-glsl Qt6::Core Qt6::Widgets novus-common) +target_include_directories(shpkpart PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_options(shpkpart PRIVATE -fexceptions) \ No newline at end of file diff --git a/parts/shpk/shpkpart.cpp b/parts/shpk/shpkpart.cpp new file mode 100644 index 0000000..b9bc085 --- /dev/null +++ b/parts/shpk/shpkpart.cpp @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2023 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "shpkpart.h" +#include "dxbc_module.h" +#include "dxbc_reader.h" +#include +#include +#include + +dxvk::Logger dxvk::Logger::s_instance("dxbc.log"); + +SHPKPart::SHPKPart(GameData *data) + : data(data) +{ + auto layout = new QVBoxLayout(); + setLayout(layout); + + pageTabWidget = new QTabWidget(); + layout->addWidget(pageTabWidget); +} + +void SHPKPart::load(physis_Buffer buffer) +{ + auto shader = physis_parse_shpk(buffer); + + pageTabWidget->clear(); + + const auto addShader = [this](physis_Shader shader, QString name) { + auto shaderTextEdit = new QTextEdit(); + shaderTextEdit->setReadOnly(true); + + dxvk::DxbcReader reader(reinterpret_cast(shader.bytecode), shader.len); + + dxvk::DxbcModule module(reader); + + dxvk::DxbcModuleInfo info; + auto result = module.compile(info, "test"); + + spirv_cross::CompilerGLSL glsl(result.code.data(), result.code.dwords()); + + glsl.build_combined_image_samplers(); + + spirv_cross::CompilerGLSL::Options options; + options.version = 310; + options.vulkan_semantics = true; + glsl.set_common_options(options); + + shaderTextEdit->setText(QLatin1String(glsl.compile().c_str())); + + pageTabWidget->addTab(shaderTextEdit, name); + }; + + for (int i = 0; i < shader.num_vertex_shaders; i++) { + addShader(shader.vertex_shaders[i], QStringLiteral("Vertex Shader %1").arg(i)); + } + + for (int i = 0; i < shader.num_pixel_shaders; i++) { + addShader(shader.pixel_shaders[i], QStringLiteral("Pixel Shader %1").arg(i)); + } +} + +#include "moc_shpkpart.cpp" \ No newline at end of file diff --git a/parts/shpk/shpkpart.h b/parts/shpk/shpkpart.h new file mode 100644 index 0000000..ccbfe66 --- /dev/null +++ b/parts/shpk/shpkpart.h @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2023 Joshua Goins +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include + +struct GameData; + +class SHPKPart : public QWidget +{ + Q_OBJECT + +public: + explicit SHPKPart(GameData *data); + + void load(physis_Buffer buffer); + +private: + QTabWidget *pageTabWidget = nullptr; + GameData *data = nullptr; +}; \ No newline at end of file