Initial commit.

This commit is contained in:
Skyth 2024-10-16 16:40:31 +03:00
commit a3e36719e7
19 changed files with 2831 additions and 0 deletions

399
.gitignore vendored Normal file
View file

@ -0,0 +1,399 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
[Oo]ut/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "vcpkg"]
path = vcpkg
url = https://github.com/microsoft/vcpkg

8
CMakeLists.txt Normal file
View file

@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.29)
include(vcpkg/scripts/buildsystems/vcpkg.cmake)
set(CMAKE_CXX_STANDARD 23)
project(ShaderRecomp-ALL)
add_subdirectory(ShaderRecomp)

28
CMakeSettings.json Normal file
View file

@ -0,0 +1,28 @@
{
"configurations": [
{
"name": "x64-Clang-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "clang_cl_x64_x64" ],
"variables": []
},
{
"name": "x64-Clang-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "clang_cl_x64_x64" ],
"variables": []
}
]
}

1
ShaderRecomp/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.hlsli.h

View file

@ -0,0 +1,23 @@
project(ShaderRecomp)
include(bin2h.cmake)
bin2h(SOURCE_FILE shader_common.hlsli HEADER_FILE shader_common.hlsli.h VARIABLE_NAME SHADER_COMMON_HLSLI)
add_executable(ShaderRecomp
constant_table.h
dxc_compiler.cpp
dxc_compiler.h
main.cpp
pch.h
shader.h
shader_code.h
shader_common.hlsli.h
shader_recompiler.cpp
shader_recompiler.h)
find_package(directx-dxc CONFIG REQUIRED)
target_link_libraries(ShaderRecomp PRIVATE Microsoft::DirectXShaderCompiler)
target_precompile_headers(ShaderRecomp PRIVATE pch.h)
add_compile_definitions(ShaderRecomp _CRT_SECURE_NO_WARNINGS)

83
ShaderRecomp/bin2h.cmake Normal file
View file

@ -0,0 +1,83 @@
# https://github.com/sivachandran/cmake-bin2h
include(CMakeParseArguments)
# Function to wrap a given string into multiple lines at the given column position.
# Parameters:
# VARIABLE - The name of the CMake variable holding the string.
# AT_COLUMN - The column position at which string will be wrapped.
function(WRAP_STRING)
set(oneValueArgs VARIABLE AT_COLUMN)
cmake_parse_arguments(WRAP_STRING "${options}" "${oneValueArgs}" "" ${ARGN})
string(LENGTH ${${WRAP_STRING_VARIABLE}} stringLength)
math(EXPR offset "0")
while(stringLength GREATER 0)
if(stringLength GREATER ${WRAP_STRING_AT_COLUMN})
math(EXPR length "${WRAP_STRING_AT_COLUMN}")
else()
math(EXPR length "${stringLength}")
endif()
string(SUBSTRING ${${WRAP_STRING_VARIABLE}} ${offset} ${length} line)
set(lines "${lines}\n${line}")
math(EXPR stringLength "${stringLength} - ${length}")
math(EXPR offset "${offset} + ${length}")
endwhile()
set(${WRAP_STRING_VARIABLE} "${lines}" PARENT_SCOPE)
endfunction()
# Function to embed contents of a file as byte array in C/C++ header file(.h). The header file
# will contain a byte array and integer variable holding the size of the array.
# Parameters
# SOURCE_FILE - The path of source file whose contents will be embedded in the header file.
# VARIABLE_NAME - The name of the variable for the byte array. The string "_SIZE" will be append
# to this name and will be used a variable name for size variable.
# HEADER_FILE - The path of header file.
# APPEND - If specified appends to the header file instead of overwriting it
# NULL_TERMINATE - If specified a null byte(zero) will be append to the byte array. This will be
# useful if the source file is a text file and we want to use the file contents
# as string. But the size variable holds size of the byte array without this
# null byte.
# Usage:
# bin2h(SOURCE_FILE "Logo.png" HEADER_FILE "Logo.h" VARIABLE_NAME "LOGO_PNG")
function(BIN2H)
set(options APPEND NULL_TERMINATE)
set(oneValueArgs SOURCE_FILE VARIABLE_NAME HEADER_FILE)
cmake_parse_arguments(BIN2H "${options}" "${oneValueArgs}" "" ${ARGN})
# reads source file contents as hex string
file(READ ${BIN2H_SOURCE_FILE} hexString HEX)
string(LENGTH ${hexString} hexStringLength)
# appends null byte if asked
if(BIN2H_NULL_TERMINATE)
set(hexString "${hexString}00")
endif()
# wraps the hex string into multiple lines at column 32(i.e. 16 bytes per line)
wrap_string(VARIABLE hexString AT_COLUMN 32)
math(EXPR arraySize "${hexStringLength} / 2")
# adds '0x' prefix and comma suffix before and after every byte respectively
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " arrayValues ${hexString})
# removes trailing comma
string(REGEX REPLACE ", $" "" arrayValues ${arrayValues})
# converts the variable name into proper C identifier
string(MAKE_C_IDENTIFIER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
# declares byte array and the length variables
set(arrayDefinition "const char ${BIN2H_VARIABLE_NAME}[] = { ${arrayValues} };")
set(arraySizeDefinition "const size_t ${BIN2H_VARIABLE_NAME}_SIZE = ${arraySize};")
set(declarations "${arrayDefinition}\n\n${arraySizeDefinition}\n\n")
if(BIN2H_APPEND)
file(APPEND ${BIN2H_HEADER_FILE} "${declarations}")
else()
file(WRITE ${BIN2H_HEADER_FILE} "${declarations}")
endif()
endfunction()

View file

@ -0,0 +1,88 @@
#pragma once
enum class ParameterClass : uint16_t // D3DXPARAMETER_CLASS
{
Scalar,
Vector,
MatrixRows,
MatrixColumns,
Object,
Struct
};
enum class ParameterType : uint16_t // D3DXPARAMETER_TYPE
{
Void,
Bool,
Int,
Float,
String,
Texture,
Texture1D,
Texture2D,
Texture3D,
TextureCube,
Sampler,
Sampler1D,
Sampler2D,
Sampler3D,
SamplerCube,
PixelShader,
VertexShader,
PixelFragment,
VertexFragment,
Unsupported
};
struct StructMemberInfo // D3DXSHADER_STRUCTMEMBERINFO
{
be<uint32_t> name;
be<uint32_t> typeInfo;
};
struct TypeInfo // D3DXSHADER_TYPEINFO
{
be<ParameterClass> parameterClass;
be<ParameterType> parameterType;
be<uint16_t> rows;
be<uint16_t> columns;
be<uint16_t> elements;
be<uint16_t> structMembers;
be<uint32_t> structMemberInfo;
};
enum class RegisterSet : uint16_t // D3DXREGISTER_SET
{
Bool,
Int4,
Float4,
Sampler
};
struct ConstantInfo // D3DXSHADER_CONSTANTINFO
{
be<uint32_t> name;
be<RegisterSet> registerSet;
be<uint16_t> registerIndex;
be<uint16_t> registerCount;
be<uint16_t> reserved;
be<uint32_t> typeInfo;
be<uint32_t> defaultValue;
};
struct ConstantTable // D3DXSHADER_CONSTANTTABLE
{
be<uint32_t> size;
be<uint32_t> creator;
be<uint32_t> version;
be<uint32_t> constants;
be<uint32_t> constantInfo;
be<uint32_t> flags;
be<uint32_t> target;
};
struct ConstantTableContainer
{
be<uint32_t> size;
ConstantTable constantTable;
};

View file

@ -0,0 +1,79 @@
#include "dxc_compiler.h"
DxcCompiler::DxcCompiler()
{
HRESULT hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler));
assert(SUCCEEDED(hr));
}
DxcCompiler::~DxcCompiler()
{
dxcCompiler->Release();
}
IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool isPixelShader, bool compileSpirv)
{
DxcBuffer source{};
source.Ptr = shaderSource.c_str();
source.Size = shaderSource.size();
const wchar_t* args[16]{};
uint32_t argCount = 0;
args[argCount++] = isPixelShader ? L"-T ps_6_0" : L"-T vs_6_0";
args[argCount++] = L"-HV 2021";
args[argCount++] = L"-all-resources-bound";
if (compileSpirv)
{
args[argCount++] = L"-spirv";
args[argCount++] = L"-fvk-use-dx-layout";
if (!isPixelShader)
args[argCount++] = L"-fvk-invert-y";
}
else
{
args[argCount++] = L"-Wno-ignored-attributes";
}
IDxcResult* result = nullptr;
HRESULT hr = dxcCompiler->Compile(&source, args, argCount, nullptr, IID_PPV_ARGS(&result));
IDxcBlob* object = nullptr;
if (SUCCEEDED(hr))
{
assert(result != nullptr);
HRESULT status;
hr = result->GetStatus(&status);
assert(SUCCEEDED(hr));
if (FAILED(status))
{
if (result->HasOutput(DXC_OUT_ERRORS))
{
IDxcBlobUtf8* errors = nullptr;
hr = result->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&errors), nullptr);
assert(SUCCEEDED(hr) && errors != nullptr);
fputs(errors->GetStringPointer(), stderr);
errors->Release();
}
}
else
{
hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&object), nullptr);
assert(SUCCEEDED(hr) && object != nullptr);
}
result->Release();
}
else
{
assert(result == nullptr);
}
return object;
}

View file

@ -0,0 +1,11 @@
#pragma once
struct DxcCompiler
{
IDxcCompiler3* dxcCompiler = nullptr;
DxcCompiler();
~DxcCompiler();
IDxcBlob* compile(const std::string& shaderSource, bool isPixelShader, bool compileSpirv);
};

83
ShaderRecomp/main.cpp Normal file
View file

@ -0,0 +1,83 @@
#include "shader.h"
#include "shader_recompiler.h"
#include "dxc_compiler.h"
static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath)
{
FILE* file = fopen(filePath, "rb");
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
auto data = std::make_unique<uint8_t[]>(fileSize);
fread(data.get(), 1, fileSize, file);
fclose(file);
return data;
}
static void writeAllBytes(const char* filePath, const void* data, size_t dataSize)
{
FILE* file = fopen(filePath, "wb");
fwrite(data, 1, dataSize, file);
fclose(file);
}
int main(int argc, char** argv)
{
if (std::filesystem::is_directory(argv[1]))
{
std::vector<std::string> filePaths;
for (auto& file : std::filesystem::directory_iterator(argv[1]))
{
auto extension = file.path().extension();
if (extension == ".xpu" || extension == ".xvu")
filePaths.push_back(file.path().string());
}
std::for_each(std::execution::par_unseq, filePaths.begin(), filePaths.end(), [&](auto& filePath)
{
printf("%s\n", filePath.c_str());
thread_local ShaderRecompiler recompiler;
recompiler = {};
recompiler.recompile(readAllBytes(filePath.c_str()).get());
writeAllBytes((filePath + ".hlsl").c_str(), recompiler.out.data(), recompiler.out.size());
thread_local DxcCompiler dxcCompiler;
auto dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false);
auto spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, true);
assert(dxil != nullptr && spirv != nullptr);
assert(*(reinterpret_cast<uint32_t*>(dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!");
std::string outFilePath = argv[2];
outFilePath += '/';
outFilePath += filePath.substr(filePath.find_last_of("\\/") + 1);
FILE* file = fopen(outFilePath.c_str(), "wb");
struct
{
uint32_t version;
uint32_t dxilSize;
uint32_t spirvSize;
} header;
header.version = 0;
header.dxilSize = uint32_t(dxil->GetBufferSize());
header.spirvSize = uint32_t(spirv->GetBufferSize());
fwrite(&header, sizeof(header), 1, file);
fwrite(dxil->GetBufferPointer(), 1, dxil->GetBufferSize(), file);
fwrite(spirv->GetBufferPointer(), 1, spirv->GetBufferSize(), file);
fclose(file);
});
}
else
{
}
return 0;
}

32
ShaderRecomp/pch.h Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include <Windows.h>
#include <dxcapi.h>
#include <bit>
#include <cassert>
#include <cstdint>
#include <execution>
#include <filesystem>
#include <format>
#include <string>
#include <unordered_map>
template<typename T>
struct be
{
T value;
T get() const
{
if constexpr (std::is_enum_v<T>)
return T(std::byteswap(std::underlying_type_t<T>(value)));
else
return std::byteswap(value);
}
operator T() const
{
return get();
}
};

107
ShaderRecomp/shader.h Normal file
View file

@ -0,0 +1,107 @@
#pragma once
#include "constant_table.h"
struct Float4Definition
{
be<uint16_t> registerIndex;
be<uint16_t> count;
be<uint32_t> physicalOffset;
};
struct Int4Definition
{
be<uint16_t> registerIndex;
be<uint16_t> count;
be<uint32_t> values[];
};
struct DefinitionTable
{
be<uint32_t> field0;
be<uint32_t> field4;
be<uint32_t> field8;
be<uint32_t> fieldC;
be<uint32_t> size;
be<uint32_t> definitions[]; // float4, int4 and bool separated by null terminators
};
struct Shader
{
be<uint32_t> physicalOffset;
be<uint32_t> size;
be<uint32_t> field8;
be<uint32_t> fieldC;
be<uint32_t> field10;
be<uint32_t> interpolatorInfo; // interpolator count: (interpolatorInfo >> 5) & 0x1F
};
enum class DeclUsage : uint32_t
{
Position = 0,
BlendWeight = 1,
BlendIndices = 2,
Normal = 3,
PointSize = 4,
TexCoord = 5,
Tangent = 6,
Binormal = 7,
TessFactor = 8,
PositionT = 9,
Color = 10,
Fog = 11,
Depth = 12,
Sample = 13
};
struct VertexElement
{
uint32_t address : 12;
DeclUsage usage : 4;
uint32_t usageIndex : 4;
};
struct Interpolator
{
uint32_t usageIndex : 4;
DeclUsage usage : 4;
uint32_t reg : 4;
uint32_t : 20;
};
struct VertexShader : Shader
{
be<uint32_t> field18;
be<uint32_t> vertexElementCount;
be<uint32_t> field20;
be<uint32_t> vertexElementsAndInterpolators[]; // field18 + vertex elements + interpolators
};
enum PixelShaderOutputs : uint32_t
{
PIXEL_SHADER_OUTPUT_COLOR0 = 0x1,
PIXEL_SHADER_OUTPUT_COLOR1 = 0x2,
PIXEL_SHADER_OUTPUT_COLOR2 = 0x4,
PIXEL_SHADER_OUTPUT_COLOR3 = 0x8,
PIXEL_SHADER_OUTPUT_DEPTH = 0x10
};
struct PixelShader : Shader
{
be<uint32_t> field18;
be<PixelShaderOutputs> outputs;
be<uint32_t> interpolators[];
};
struct ShaderContainer
{
be<uint32_t> flags;
be<uint32_t> virtualSize;
be<uint32_t> physicalSize;
be<uint32_t> fieldC;
be<uint32_t> constantTableOffset;
be<uint32_t> definitionTableOffset;
be<uint32_t> shaderOffset;
be<uint32_t> field1C;
be<uint32_t> field20;
};

458
ShaderRecomp/shader_code.h Normal file
View file

@ -0,0 +1,458 @@
#pragma once
enum class ControlFlowOpcode : uint32_t
{
Nop = 0,
Exec = 1,
ExecEnd = 2,
CondExec = 3,
CondExecEnd = 4,
CondExecPred = 5,
CondExecPredEnd = 6,
LoopStart = 7,
LoopEnd = 8,
CondCall = 9,
Return = 10,
CondJmp = 11,
Alloc = 12,
CondExecPredClean = 13,
CondExecPredCleanEnd = 14,
MarkVsFetchDone = 15,
};
struct ControlFlowExecInstruction
{
uint32_t address : 12;
uint32_t count : 3;
uint32_t isYield : 1;
uint32_t sequence : 12;
uint32_t vertexCacheHigh : 4;
uint32_t vertexCacheLow : 2;
uint32_t : 7;
uint32_t isPredicateClean : 1;
uint32_t : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowExecPredInstruction
{
uint32_t address : 12;
uint32_t count : 3;
uint32_t isYield : 1;
uint32_t sequence : 12;
uint32_t vertexCacheHigh : 4;
uint32_t vertexCacheLow : 2;
uint32_t : 7;
uint32_t isPredicateClean : 1;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowCondExecInstruction
{
uint32_t address : 12;
uint32_t count : 3;
uint32_t isYield : 1;
uint32_t sequence : 12;
uint32_t vertexCacheHigh : 4;
uint32_t vertexCacheLow : 2;
uint32_t boolAddress : 8;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowCondExecPredInstruction
{
uint32_t address : 12;
uint32_t count : 3;
uint32_t isYield : 1;
uint32_t sequence : 12;
uint32_t vertexCacheHigh : 4;
uint32_t vertexCacheLow : 2;
uint32_t : 7;
uint32_t isPredicateClean : 1;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowLoopStartInstruction
{
uint32_t address : 13;
uint32_t isRepeat : 1;
uint32_t : 2;
uint32_t loopId : 5;
uint32_t : 11;
uint32_t : 11;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowLoopEndInstruction
{
uint32_t address : 13;
uint32_t : 3;
uint32_t loopId : 5;
uint32_t isPredicatedBreak : 1;
uint32_t : 10;
uint32_t : 10;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowCondCallInstruction
{
uint32_t address : 13;
uint32_t isUnconditional : 1;
uint32_t isPredicated : 1;
uint32_t : 17;
uint32_t : 2;
uint32_t boolAddress : 8;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowReturnInstruction
{
uint32_t : 32;
uint32_t : 11;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowCondJmpInstruction
{
uint32_t address : 13;
uint32_t isUnconditional : 1;
uint32_t isPredicated : 1;
uint32_t : 17;
uint32_t : 1;
uint32_t direction : 1;
uint32_t boolAddress : 8;
uint32_t condition : 1;
uint32_t absoluteAddressing : 1;
ControlFlowOpcode opcode : 4;
};
struct ControlFlowAllocInstruction
{
uint32_t size : 3;
uint32_t : 29;
uint32_t : 8;
uint32_t isUnserialized : 1;
uint32_t allocType : 2;
uint32_t : 1;
ControlFlowOpcode opcode : 4;
};
union ControlFlowInstruction
{
ControlFlowExecInstruction exec;
ControlFlowCondExecInstruction condExec;
ControlFlowCondExecPredInstruction condExecPred;
ControlFlowLoopStartInstruction loopStart;
ControlFlowLoopEndInstruction loopEnd;
ControlFlowCondCallInstruction condCall;
ControlFlowReturnInstruction ret;
ControlFlowCondJmpInstruction condJmp;
ControlFlowAllocInstruction alloc;
struct
{
uint32_t : 32;
uint32_t : 12;
ControlFlowOpcode opcode : 4;
};
};
enum class FetchOpcode : uint32_t
{
VertexFetch = 0,
TextureFetch = 1,
GetTextureBorderColorFrac = 16,
GetTextureComputedLod = 17,
GetTextureGradients = 18,
GetTextureWeights = 19,
SetTextureLod = 24,
SetTextureGradientsHorz = 25,
SetTextureGradientsVert = 26
};
enum class FetchDestinationSwizzle : uint32_t
{
X = 0,
Y = 1,
Z = 2,
W = 3,
Zero = 4,
One = 5,
Keep = 7
};
struct VertexFetchInstruction
{
struct
{
FetchOpcode opcode : 5;
uint32_t srcRegister : 6;
uint32_t srcRegisterAm : 1;
uint32_t dstRegister : 6;
uint32_t dstRegisterAam : 1;
uint32_t mustBeOne : 1;
uint32_t constIndex : 5;
uint32_t constIndexSelect : 2;
uint32_t prefetchCount : 3;
uint32_t srcSwizzle : 2;
};
struct
{
uint32_t dstSwizzle : 12;
uint32_t formatCompAll : 1;
uint32_t numFormatAll : 1;
uint32_t signedRfModeAll : 1;
uint32_t isIndexRounded : 1;
uint32_t format : 6;
uint32_t reserved2 : 2;
int32_t expAdjust : 6;
uint32_t isMiniFetch : 1;
uint32_t isPredicated : 1;
};
struct
{
uint32_t stride : 8;
int32_t offset : 23;
uint32_t predicateCondition : 1;
};
};
enum class TextureDimension : uint32_t
{
Texture1D,
Texture2D,
Texture3D,
TextureCube
};
struct TextureFetchInstruction
{
struct
{
FetchOpcode opcode : 5;
uint32_t srcRegister : 6;
uint32_t srcRegisterAm : 1;
uint32_t dstRegister : 6;
uint32_t dstRegisterAm : 1;
uint32_t fetchValidOnly : 1;
uint32_t constIndex : 5;
uint32_t texCoordDenorm : 1;
uint32_t srcSwizzle : 6;
};
struct
{
uint32_t dstSwizzle : 12;
uint32_t magFilter : 2;
uint32_t minFilter : 2;
uint32_t mipFilter : 2;
uint32_t anisoFilter : 3;
uint32_t arbitraryFilter : 3;
uint32_t volMagFilter : 2;
uint32_t volMinFilter : 2;
uint32_t useCompLod : 1;
uint32_t useRegLod : 1;
uint32_t : 1;
uint32_t isPredicated : 1;
};
struct
{
uint32_t useRegGradients : 1;
uint32_t sampleLocation : 1;
int32_t lodBias : 7;
uint32_t : 5;
TextureDimension dimension : 2;
int32_t offsetX : 5;
int32_t offsetY : 5;
int32_t offsetZ : 5;
uint32_t predCondition : 1;
};
};
union FetchInstruction
{
VertexFetchInstruction vertexFetch;
TextureFetchInstruction textureFetch;
struct
{
FetchOpcode opcode : 5;
uint32_t : 27;
uint32_t : 32;
};
};
enum class AluScalarOpcode : uint32_t
{
Adds = 0,
AddsPrev = 1,
Muls = 2,
MulsPrev = 3,
MulsPrev2 = 4,
Maxs = 5,
Mins = 6,
Seqs = 7,
Sgts = 8,
Sges = 9,
Snes = 10,
Frcs = 11,
Truncs = 12,
Floors = 13,
Exp = 14,
Logc = 15,
Log = 16,
Rcpc = 17,
Rcpf = 18,
Rcp = 19,
Rsqc = 20,
Rsqf = 21,
Rsq = 22,
MaxAs = 23,
MaxAsf = 24,
Subs = 25,
SubsPrev = 26,
SetpEq = 27,
SetpNe = 28,
SetpGt = 29,
SetpGe = 30,
SetpInv = 31,
SetpPop = 32,
SetpClr = 33,
SetpRstr = 34,
KillsEq = 35,
KillsGt = 36,
KillsGe = 37,
KillsNe = 38,
KillsOne = 39,
Sqrt = 40,
Mulsc0 = 42,
Mulsc1 = 43,
Addsc0 = 44,
Addsc1 = 45,
Subsc0 = 46,
Subsc1 = 47,
Sin = 48,
Cos = 49,
RetainPrev = 50
};
enum class AluVectorOpcode : uint32_t
{
Add = 0,
Mul = 1,
Max = 2,
Min = 3,
Seq = 4,
Sgt = 5,
Sge = 6,
Sne = 7,
Frc = 8,
Trunc = 9,
Floor = 10,
Mad = 11,
CndEq = 12,
CndGe = 13,
CndGt = 14,
Dp4 = 15,
Dp3 = 16,
Dp2Add = 17,
Cube = 18,
Max4 = 19,
SetpEqPush = 20,
SetpNePush = 21,
SetpGtPush = 22,
SetpGePush = 23,
KillEq = 24,
KillGt = 25,
KillGe = 26,
KillNe = 27,
Dst = 28,
MaxA = 29
};
enum class ExportRegister : uint32_t
{
VSInterpolator0 = 0,
VSInterpolator1,
VSInterpolator2,
VSInterpolator3,
VSInterpolator4,
VSInterpolator5,
VSInterpolator6,
VSInterpolator7,
VSInterpolator8,
VSInterpolator9,
VSInterpolator10,
VSInterpolator11,
VSInterpolator12,
VSInterpolator13,
VSInterpolator14,
VSInterpolator15,
VSPosition = 62,
VSPointSizeEdgeFlagKillVertex = 63,
PSColor0 = 0,
PSColor1,
PSColor2,
PSColor3,
PSDepth = 61,
ExportAddress = 32,
ExportData0 = 33,
ExportData1,
ExportData2,
ExportData3,
ExportData4,
};
struct AluInstruction
{
struct
{
uint32_t vectorDest : 6;
uint32_t vectorDestRelative : 1;
uint32_t absConstants : 1;
uint32_t scalarDest : 6;
uint32_t scalarDestRelative : 1;
uint32_t exportData : 1;
uint32_t vectorWriteMask : 4;
uint32_t scalarWriteMask : 4;
uint32_t vectorSaturate : 1;
uint32_t scalarSaturate : 1;
AluScalarOpcode scalarOpcode : 6;
};
struct
{
uint32_t src3Swizzle : 8;
uint32_t src2Swizzle : 8;
uint32_t src1Swizzle : 8;
uint32_t src3Negate : 1;
uint32_t src2Negate : 1;
uint32_t src1Negate : 1;
uint32_t predicateCondition : 1;
uint32_t isPredicated : 1;
uint32_t constAddressRegisterRelative : 1;
uint32_t const1Relative : 1;
uint32_t const0Relative : 1;
};
struct
{
uint32_t src3Register : 8;
uint32_t src2Register : 8;
uint32_t src1Register : 8;
AluVectorOpcode vectorOpcode : 5;
uint32_t src3Select : 1;
uint32_t src2Select : 1;
uint32_t src1Select : 1;
};
};

View file

@ -0,0 +1,80 @@
#define FLT_MIN asfloat(0xff7fffff)
#define FLT_MAX asfloat(0x7f7fffff)
#ifdef __spirv__
struct PushConstants
{
uint64_t VertexShaderConstants;
uint64_t PixelShaderConstants;
uint64_t SharedConstants;
};
[[vk::push_constant]] ConstantBuffer<PushConstants> g_PushConstants;
#define CONSTANT_BUFFER(NAME, REGISTER) struct NAME
#define PACK_OFFSET(REGISTER)
#define GET_CONSTANT(NAME) constants.NAME
#define GET_SHARED_CONSTANT(NAME) sharedConstants.NAME
#else
#define CONSTANT_BUFFER(NAME, REGISTER) cbuffer NAME : register(REGISTER, space4)
#define PACK_OFFSET(REGISTER) : packoffset(REGISTER)
#define GET_CONSTANT(NAME) NAME
#define GET_SHARED_CONSTANT(NAME) NAME
#endif
#define INPUT_LAYOUT_FLAG_HAS_R11G11B10_NORMAL (1 << 0)
#define SHARED_CONSTANTS \
[[vk::offset(128)]] uint g_AlphaTestMode PACK_OFFSET(c8.x); \
[[vk::offset(132)]] float g_AlphaThreshold PACK_OFFSET(c8.y); \
[[vk::offset(136)]] uint g_Booleans PACK_OFFSET(c8.z); \
[[vk::offset(140)]] uint g_SwappedTexcoords PACK_OFFSET(c8.w); \
[[vk::offset(144)]] uint g_InputLayoutFlags PACK_OFFSET(c9.x)
Texture2D<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1);
TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2);
SamplerState g_SamplerDescriptorHeap[] : register(s0, space3);
float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord)
{
return g_Texture2DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord);
}
float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord)
{
return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord);
}
float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float4 texCoord)
{
return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord.xyz);
}
float4 tfetchR11G11B10(uint inputLayoutFlags, uint4 value)
{
if (inputLayoutFlags & INPUT_LAYOUT_FLAG_HAS_R11G11B10_NORMAL)
{
return float4(
(value.x & 0x00000400 ? -1.0 : 0.0) + ((value.x & 0x3FF) / 1024.0),
(value.x & 0x00200000 ? -1.0 : 0.0) + (((value.x >> 11) & 0x3FF) / 1024.0),
(value.x & 0x80000000 ? -1.0 : 0.0) + (((value.x >> 22) & 0x1FF) / 512.0),
0.0);
}
else
{
return asfloat(value);
}
}
float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex)
{
return (swappedTexcoords & (1 << semanticIndex)) != 0 ? value.yxwz : value;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
#pragma once
#include "shader.h"
#include "shader_code.h"
struct ShaderRecompiler
{
std::string out;
uint32_t indentation = 0;
bool isPixelShader = false;
const uint8_t* constantTableData = nullptr;
std::unordered_map<uint32_t, VertexElement> vertexElements;
std::unordered_map<uint32_t, std::string> interpolators;
std::unordered_map<uint32_t, const ConstantInfo*> float4Constants;
std::unordered_map<uint32_t, const char*> boolConstants;
std::unordered_map<uint32_t, const char*> samplers;
void indent()
{
for (uint32_t i = 0; i < indentation; i++)
out += '\t';
}
template<class... Args>
void print(std::format_string<Args...> fmt, Args&&... args)
{
std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
}
template<class... Args>
void println(std::format_string<Args...> fmt, Args&&... args)
{
std::vformat_to(std::back_inserter(out), fmt.get(), std::make_format_args(args...));
out += '\n';
}
void printDstSwizzle(uint32_t dstSwizzle, bool operand);
void printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle);
void recompile(const VertexFetchInstruction& instr, uint32_t address);
void recompile(const TextureFetchInstruction& instr);
void recompile(const AluInstruction& instr);
void recompile(const uint8_t* shaderData);
};

1
vcpkg Submodule

@ -0,0 +1 @@
Subproject commit e63bd09dc0b7204467705c1c7c71d0e2a3f8860b

6
vcpkg.json Normal file
View file

@ -0,0 +1,6 @@
{
"builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
"dependencies": [
"directx-dxc"
]
}